依賴注入
首先需要解釋一下什么是依賴注入(Dependency Injection),依賴注入據我的理解就是把在一個類中的屬性的實例化不在內部實例化,而是在外部進行實例化。常見為把該類中屬性的對象作為一個參數傳入,然后賦值給該屬性。目的是則是為了降低耦合性。要先了解這個是因為這個東東將會在設計模式中大規模應用。
具體代碼如下:
public interface IPhone
{
void call();
}
public class iphone4:phone
{
void call()
{
//todo
}
}
public class People
{
IPhone myphone;
public void phone (IPhone _phone)
{
this.myphone=_phone;
}
public void call()
{
myphone.call();
}
}
上述可以描述的很簡單,1:要建造的類:people 2:傳入的參數:具體的手機對象,3:使用到的傳入對象的屬性或方法:call.我暫時杜撰此種翻譯名稱為DI2C( Dependency Injection TO CHINESE )描述。(反正四書五經都是杜撰的)。
設計模式原則與警句
- OO設計需要把握可復用,可擴展,可維護三個原則。
- 我們把系統中的會變化的部分抽出來封裝
- 開放封閉原則:對修改封閉,對擴展開放。
- 多用組合,少用繼承。
- 最少知識原則:只和你的密友談話。
設計模式
本文只闡述思想,以及一種一對多映射的記憶方法,具體代碼就不貼出了。
1 策略模式,
上述例子中是可以把iphone傳入的,策略模式中,比如還是按照如上例子,還是寫人這個類,則可以把人的具體的唱歌方式傳入,如傳入高音,低音等,把唱歌方式的對象作為一個參數傳入。
用DI2C可以描述成
- 要聲明的類 :策略使用者
- 傳入的參數:具體的策略。
- 使用到的傳入對象的屬性或方法:傳入策略的具體方法。
對本模式的感想就是要調用方法能不能直接委托傳入啊。
2 觀察者模式
也叫訂閱模式,就是火警報警器發現着火了然后通知所有辦公室的人逃出去這樣,或者一家天氣預報通知所有訂了他們信息通知的人
這個模式也是用了依賴注入.首先是定義觀察並通知信息的人的接口(有三個方法,register(),delete(),notify())和被通知信息的人的接口(因為可能有多個觀察者)。然后定義一個觀察者類和被觀察者類分別繼承上述兩個接口。定義接口是為了規定該類必須實現的方法以及可以實現多態以實現依賴注入。觀察者類中可以聲明一個被觀察List類用來管理被觀察者。register()用來在list中增加被觀察者,delete()能在list中去掉一個被觀察者。而notify()則通知所有觀察者。
觀察者中的依賴注入:
- 首先要聲明的類:觀察者。
- 傳入的參數:被觀察者。
- 使用到的屬性或方法:被觀者的信息,比如手機號碼用來發通知信息等等。
3 裝飾模式
裝飾模式就是不斷在一個類中注入另一個類。比如一個人,套上T-shirt,套上褲子,套上外套,等等,都是在一個類中加上衣服類。由於需要套上之后還是一個人類。裝飾模式中,不斷將人那個類注入到衣服類中。所以裝飾類就有必要也繼承於人類。其實我在這里覺得這樣很別扭,裝飾類繼承於人,那還叫裝飾類嗎,不是該叫裝飾的人嗎,人類含着人類那不叫懷孕嗎。在我看來還不如直接在people類中建立一個衣服類的泛型,然后將一個一個衣服類add進去,展示的時候按順序display出來。個人想法,歡迎大家一起討論。
總結一下
- 首先要聲明的類:被裝飾者類
- 傳入的參數:裝飾品類(衣服,機器組件等等)
- 使用到的屬性和方法:如游戲中展示人物,需要把衣服一件一件的展示出來,就需要用到每一件衣服的展示功能。
4 工廠模式
這里談個問題。
這個模式開始我覺得很雞肋。因為本來直接聲明一個類,現在卻先聲明一個工廠然后通過工廠來聲明一個實例。
原來的
IConcrete InstanceA=new ConcreteA();
IConcrete InstanceB=new ConcreteB();
現在要寫成
IFactory factoryInstanceA=new FactoryA();
IConcreteA InstanceA=factoryInstanceA.CreateInstance();
IFactory factoryInstanceB=new FactoryB();
IConcreteA InstanceB=factoryInstanceB.CreateInstance();
不但原本好好的一句話搞定的事情變成了兩句話,另外增加一個ConcreteB 類的同時要增加一個對應的工廠類。着實讓我看不太懂。后來搜了一下說是為了封裝實例創建過程。
“為什么要封裝實例創建過程?”
上網搜了一下很難搜到,總結出來兩點
- 類名很長或者實例化過程比較復雜的時候,那么就用工廠方法比較好。
- 這個類的創建過程以后很可能會發生變化。這個時候改變具體創建方法內部代碼就不會影響客戶端代碼。
然后我就想,這個工廠方法還是在合適的時候用,不然只會越用越復雜。特別如果使用三層架構時,你能想象在Model層中每個類中再加一個相對應的工廠類生產專門的類嗎。但是如果有需要的情況下還是能好的解耦的。我覺得小系統中是沒必要用。大系統的話對維護要求比較高的情況下用用還是不錯的。
就拿做pizza來說,今天創建可能是拿的是小作坊的手工制造,過幾年小作坊變牛X了用的都是機器,或者披薩的原料變了,實例化的參數不一樣了,這個時候改變參數就不會有修改客戶端的問題。
5 單例模式
怎么做到讓一個類不能被重復實例化呢。老婆什么的可不能到處實例化啊。
三步走,
1把該類的構造方法私有化,這樣別人就不可以隨便實例化啦。
2在類內部聲明一個與該類同類型的對象指向null(私有靜態)。(如private static LP A;)
3把第二部中的對象實例化這個過程放到內部的一個CreateInstance方法中調用,如果對象已經不為null,則實例化,否則直接直接返回。
怎么應對並發請搜索雙重鎖定在此不再多講。
6 適配器模式
用過非國行的手機的人都知道,會有一個電壓轉換器,因為國內外的電壓時不同的,所以就需要轉換電壓。而這個適配器模式就是充當類似電壓轉換器的作用。
首先這里也用到了依賴注入,
要聲明的類:適配器類(繼承想要轉化成的類型接口,因為這里要遵循接口規范)
傳入的參數:需要被轉化的對象
使用到的屬性或者方法:這里的方法是適配器自己定義的方法,調用注入對象的屬性進行一些列轉化算法之后輸出。
適配器還分對象適配器和類適配器
7 外觀模式
外觀模式,把一些組件的功能組織起來一起調用。比如開機,開啟windows,開啟360,開啟搜狗輸入法,開啟有道詞典這一系列經常要用的軟件可以開機啟動,就需要這一系列動作放到一起去執行。只需要把windows,360,搜狗輸入法等對象注入一個類,然后由這個類集中初始化就行了。
要聲明的類:調用者客戶端,如電腦,軟件。
傳入的參數:需要被集中調用的對象。
使用到的屬性或方法:集中調用的方法。如電腦的開機方法等等。
外觀模式讓使用者更加方便,提供一鍵操作方式。
8 模板方法模式
模板方法模式定義一個操作的算法骨架,而將一些步驟延遲到子類中去實現,可以不改變一個算法的結構即可以重新定義概算法的某些特定步驟。就是定義一個抽象基類,里面的一些方法已經定義好,還有一些虛方法未繼承,可以用子類按需要繼承該基類然后實現里面沒實現的方法。
首先個人覺得這個方法還是比較好用的。但是說白了也就是抽象類最基本的使用,如果抽象類用的多了自然就會這種模式了。這個模式只要會用abstract的都基本自然會用,沒必要多看。
9 迭代器模式
迭代器模式我們用的不要太多,最簡單的foreach就是用迭代器模式實現的。數據結構中我們知道,鏈表的遍歷實現,while(P->next!=null) p=p.next。這一小段代碼是用來遍歷鏈表的。我覺得迭代器模式就很像。一個迭代器接口方法里面有三個主要方法,一個是利用依賴注入把要遍歷的數組對象傳入迭代器的。然后就是hasNext()方法和Next()方法。hasNext用來判斷是否有有下一個,如果有則利用Next()方法返回下一個item,然后操作這個item()。這就是迭代器方法的本質。這個模式有了foreach之后基本就用不到了,了解即可。
10組合模式
組合模式不是很難。但是簡單的東西都不好描述。組合模式講述的是一個樹形結構,一個根節點會有一些孩子節點,這些孩子節點可能是葉子節點(沒有子節點),也可能是其他節點的父節點。我們把節點抽象成一個基類,所有的普通節點和父節點都將繼承這個基類。這個基類有一些方法,比如可以添加孩子節點,去掉孩子節點,這樣這個基類就需要add(),remove()方法,其他的方法可以依據具體信息而表現出來。他還需要一個泛型List管理他的的孩子節點。這樣,樹與樹,節點與樹,節點與節點都可以構成一棵樹。而構成后的樹,可以繼續擴展開來。這就是組合模式,其實就是數據結構里的樹形結構,如果你看不懂我說的這段,建議你看完源代碼你就理解了。
因為一些原因,先寫這么些部分,下次再繼續寫。
歡迎園友們來一起討論,無論褒貶我都會虛心接受,您的支持是我的動力。