Summary:若干客戶使用類接口中的同一子集,或者兩個類的接口有相同部分。將相同的子集提煉到一個獨立接口中。 java
動機:程序員
類之間彼此相互用的方式有若干種。「使用一個類」一般意味用到該類的全部責任區。另外一種狀況是,某一組客戶只使用類責任區中的一個特定子集。再一種狀況則是,這個類須要與全部協助處理某些特定請求的類合做。函數
對於後兩種狀況,將真正用到的這部分責任分離出來一般頗有意義,由於這樣可使系統的用法更清晰,同時也更容易看清系統的責任劃分。若是新的類須要支持上述子集,也比較可以看清子集內有些什麼東西。spa
在許多面向對象語言中,這種責任劃分是經過多繼承(multiple inheritance)來實現的。你能夠針對每組行爲創建一個類,再將它們組合於同一個實現中。Java只提供單繼承(single inheritance),但你能夠運用接口來昭示並事項上述需求。接口對於java 程序的設計方式有着巨大的影響,就連Smalltalk程序員都認爲接口是一大進步。設計
Extract Superclass 和Extract Interface之間有些類似之處。Extract Interface 只能提煉共通接口,不能提煉共通代碼。使用Extract Interface可能形成難聞的「重複」壞味道,幸而你能夠運用Extract Class 先把共通行爲放進一個組件中,而後將工做委託該組件,從而解決這個問題。若是有很多共通行爲,Extract Superclass會比較簡單,可是每一個類只能有一個超類。code
若是某個類在不一樣環境下扮演大相徑庭的角色,使用接口就是個好主意。你能夠針對每一個角色以Extract Interface提煉出相應接口。另外一種能夠用上Extract Interface的狀況是:你想要描述一個類的外部依賴接口(outbound interface,即這個類要求服務提供方提供的操做)。若是你打算未來加入其餘種類的服務對象,只須要求它們實現這個接口便可。對象
作法: 繼承
1.新建一個空接口接口
2.在接口中聲明待提煉類的共通操做。ip
3.讓相關的類實現上述接口
4.調整客戶端的類型聲明,令其使用該接口。
範例:
TimeSheet類表示員工爲客戶工做的時間表,從中能夠計算客戶應該支付的費用。爲了計算這筆費用,TimeSheet須要知道員工級別,以及員工是否有特殊技能
double charge(Employee emp,int days){ int base = emp.getRate() * days; if(emp.hasSpecialSkill()){ return base * 1.05; }else{ return base; } }
除了提供員工的級別和特殊技能信息外,Employee還有不少其餘方面的功能,但本應用程序只需這兩項功能。咱們能夠針對這兩項功能定義一個接口,從而強調「我只須要這部分功能」的事實:
interface Billable{ public int getRate(); public boolean hasSpecialSkill(); }
而後,聲明讓Employee實現這個接口
class Employee implements Billable
完成之後,修改charge()函數聲明,強調改函數只使用Employee的這部分行爲
double charge(Billable emp, int days){ int base = emp.getRate() * days; if(emp.hasSpecialSkill()){ return base * 1.05; }else{ return base; } }
到目前爲止,咱們只不過是在文檔化方面有一點收穫。單就這一個函數而言,這樣的收穫並無太大價值;但若是有若干個類都是用Billable接口,它就頗有用。若是我還想計算電腦租金,巨大的收穫就顯露出來了:要想計算客戶租用電腦的費用,只需讓Computer類實現Billable接口,而後就能夠把租用電腦的時間也填到時間表上了。