0.提前說明
模式選擇的方法
1)模式的功能——看是否能解決問題
2)模式的本質(zhì)——看模式是否主要用來解決這類問題
3)模式的適用程度——看使用這個模式是否貼切,看是否需要變形
4)應(yīng)用模式的復(fù)雜程度——看使用模式帶來的開發(fā)復(fù)雜度是否可接受或可控
5)應(yīng)用模式的代價——看使用模式的代價是否可接受或可控,如:引入過多的對象、耗費更多的內(nèi)存等很多模式都可以組合使用,并不局限于這里要講的
有些模式功能相近,結(jié)構(gòu)類似,要特別注意他們的辨析
掌握模式一定要從思想上、本質(zhì)上、整體上去把握
1. 簡單工廠的相關(guān)模式
1.1 簡單工廠和抽象工廠模式
簡單工廠是用來選擇實現(xiàn)的,可以選擇任意接口的實現(xiàn),一個簡單工廠可以有多個用于選擇并創(chuàng)建對象的方法,多個方法創(chuàng)建的對象可以有關(guān)系也可以沒有關(guān)系。
抽象工廠模式是用來選擇產(chǎn)品簇的實現(xiàn)的,也就是說一般抽象工廠里面有多個用于選擇并創(chuàng)建對象的方法,但是這些方法所創(chuàng)建的對象之間通常是有關(guān)系的,這些被創(chuàng)建的對象通常是構(gòu)成一個產(chǎn)品簇所需要的部件對象。
所以從某種意義上來說,簡單工廠和抽象工廠是類似的,如果抽象工廠退化成為只有一個實現(xiàn),不分層次,那么就相當于簡單工廠了。
1.2 簡單工廠和工廠方法模式
簡單工廠和工廠方法模式也是非常類似的。
工廠方法的本質(zhì)也是用來選擇實現(xiàn)的,跟簡單工廠的區(qū)別在于工廠方法是把選擇具體實現(xiàn)的功能延遲到子類去實現(xiàn)。
如果把工廠方法中選擇的實現(xiàn)放到父類直接實現(xiàn),那就等同于簡單工廠
1.3 簡單工廠和能創(chuàng)建對象實例的模式
簡單工廠的本質(zhì)是選擇實現(xiàn),所以它可以跟其它任何能夠具體的創(chuàng)建對象實例的模式配合使用,比如:單例模式、原型模式、生成器模式等等。
2.外觀模式的相關(guān)模式
2.1 外觀模式和中介者模式
這兩個模式非常類似,但是有本質(zhì)的區(qū)別。
中介者模式主要用來封裝多個對象之間相互的交互,多用在系統(tǒng)內(nèi)部的多
個模塊之間;而外觀模式封裝的是單向的交互,是從客戶端訪問系統(tǒng)的調(diào)用,沒有從系統(tǒng)中來訪問客戶端的調(diào)用。
在中介者模式的實現(xiàn)里面,是需要實現(xiàn)具體的交互功能的;而外觀模式的實現(xiàn)里面,一般是組合調(diào)用或是轉(zhuǎn)調(diào)內(nèi)部實現(xiàn)的功能,通常外觀模式本身并不實現(xiàn)這些功能。
中介者模式的目的主要是松散多個模塊之間的耦合,把這些耦合關(guān)系全部放到中介者中去實現(xiàn);而外觀模式的目的是簡化客戶端的調(diào)用,這點和中介者模式也不同。
2.2 外觀模式和單例模式
通常一個子系統(tǒng)只需要一個外觀實例,所以外觀模式可以和單例模式組合使用,把Facade類實現(xiàn)成為單例。當然,也可以跟前面示例的那樣,把外觀類的構(gòu)造方法私有化,然后把提供給客戶端的方法實現(xiàn)成為靜態(tài)的
2.3 外觀模式和抽象工廠模式
外觀模式的外觀類通常需要和系統(tǒng)內(nèi)部的多個模塊交互,每個模塊一般都有自己的接口,所以在外觀類的具體實現(xiàn)里面,需要獲取這些接口,然后組合這些接口來完成客戶端的功能。
那么怎么獲取這些接口呢?就可以和抽象工廠一起使用,外觀類通過抽象工廠來獲取所需要的接口,而抽象工廠也可以把模塊內(nèi)部的實現(xiàn)對Facade進行屏蔽,也就是說Facade也僅僅只是知道它從模塊中獲取的它需要的功能,模塊內(nèi)部的細節(jié),F(xiàn)acade也不知道了。
3.適配器模式的相關(guān)模式
3.1 適配器模式與橋接模式
其實這兩個模式除了結(jié)構(gòu)略為相似外,功能上完全不同。
適配器模式是把兩個或者多個接口的功能進行轉(zhuǎn)換匹配;而橋接模式是讓接口和實現(xiàn)部分相分離,以便它們可以相對獨立的變化。
3.2 適配器模式與裝飾模式
從某種意義上講,適配器模式能模擬實現(xiàn)簡單的裝飾模式的功能,也就是為已有功能增添功能。
造成這種類似的原因:兩種設(shè)計模式在實現(xiàn)上都是使用的對象組合,都可以在轉(zhuǎn)調(diào)組合對象的功能前后進行一些附加的處理,因此有這么一個相似性。它們的目的和本質(zhì)都是不一樣的。
兩個模式有一個很大的不同:一般適配器適配過后是需要改變接口的,如果不改接口就沒有必要適配了;而裝飾模式是不改接口的,無論多少層裝飾都是一個接口。
因此裝飾模式可以很容易的支持遞歸組合,而適配器就做不到了,每次的接口不同,沒法遞歸。
3.3 適配器模式和代理模式
適配器模式可以跟代理模式組合使用,在實現(xiàn)適配器的時候,可以通過代理來調(diào)用Adaptee,這可以獲得更大的靈活性
3.4 適配器模式和抽象工廠模式
在適配器實現(xiàn)的時候,通常需要得到被適配的對象,如果被適配的是一個接口,那么就可以結(jié)合一些可以創(chuàng)造對象實例的設(shè)計模式,來得到被適配的對象示例。比如:抽象工廠模式、單例模式、工廠方法模式等
4.單例模式的相關(guān)模式
很多模式都可以使用單例模式,只要這些模式中的某個類,需要控制實例為一個的時候,就可以很自然的使用上單例模式。比如抽象工廠方法中的具體工廠類就通常是一個單例。
5.工廠方法模式的相關(guān)模式
5.1 工廠方法模式和抽象工廠模式
這兩個模式可以組合使用,具體的放到抽象工廠模式中去講。
5.2 工廠方法模式和模板方法模式
這兩個模式外觀類似,都是有一個抽象類,然后由子類來提供一些實現(xiàn),但是工廠方法模式的子類專注的是創(chuàng)建產(chǎn)品對象,而模板方法模式的子類專注的是為固定的算法骨架提供某些步驟的實現(xiàn)。
這兩個模式可以組合使用,通常在模板方法模式里面,使用工廠方法來創(chuàng)建模板方法需要的對象。
6.抽象工廠模式的相關(guān)模式
6.1 抽象工廠模式和工廠方法模式
這兩個模式既有區(qū)別,又有聯(lián)系,可以組合使用。
工廠方法模式一般是針對單獨的產(chǎn)品對象的創(chuàng)建,而抽象工廠模式注重產(chǎn)品簇對象的創(chuàng)建,這是它們的區(qū)別。
如果把抽象工廠創(chuàng)建的產(chǎn)品簇簡化,這個產(chǎn)品簇就只有一個產(chǎn)品,那么這個時候的抽象工廠跟工廠方法是差不多的,也就是抽象工廠可以退化成工廠方法,而工廠方法又可以退化成簡單工廠,這是它們的聯(lián)系。
在抽象工廠的實現(xiàn)中,還可以使用工廠方法來提供抽象工廠的具體實現(xiàn),也就是說它們可以組合使用。
6.2 抽象工廠模式和單例模式
這兩個模式可以組合使用。
在抽象工廠模式里面,具體的工廠實現(xiàn),在整個應(yīng)用中,通常一個產(chǎn)品系列只需要一個實例就可以了,因此可以把具體的工廠實現(xiàn)成為單例。
7.生成器模式的相關(guān)模式
7.1 生成器模式和工廠方法模式
這兩個模式可以組合使用。
生成器模式的Builder實現(xiàn)中,通常需要選擇具體的部件實現(xiàn),一個可行的方案就是實現(xiàn)成為工廠方法,通過工廠方法來獲取具體的部件對象,然后再進行部件的裝配。
7.2 生成器模式和抽象工廠模式
這兩個模式既相似又有區(qū)別,也可以組合使用
先說相似性,這個在課程里面已經(jīng)詳細講述了,這里就不去重復(fù)了。
再說說區(qū)別:抽象工廠模式的主要目的是創(chuàng)建產(chǎn)品簇,這個產(chǎn)品簇里面的單個產(chǎn)品,就相當于是構(gòu)成一個復(fù)雜對象的部件對象,抽象工廠對象創(chuàng)建完成過后就立即返回整個產(chǎn)品簇;而生成器模式的主要目的是按照構(gòu)造算法,一步一步來構(gòu)建一個復(fù)雜的產(chǎn)品對象,通常要等到整個構(gòu)建過程結(jié)束過后,才會得到最終的產(chǎn)品對象。
事實上,這兩個模式是可以組合使用的,在生成器模式的Builder實現(xiàn)中,需要創(chuàng)建各個部件對象,而這些部件對象是有關(guān)聯(lián)的,通常是構(gòu)成一個復(fù)雜對象的部件對象,也就是說,Builder實現(xiàn)中,需要獲取構(gòu)成一個復(fù)雜對象的產(chǎn)品簇,那自然就可以使用抽象工廠模式來實現(xiàn)。這樣一來,由抽象工廠模式負責了部件對象的創(chuàng)建,Builder實現(xiàn)里面就主要負責產(chǎn)品對象整體的構(gòu)建了。
7.3 生成器模式和模板方法模式
這也是兩個非常類似的模式。初看之下,不會覺得這兩個模式有什么關(guān)聯(lián),但是仔細一思考,發(fā)現(xiàn)兩個模式在功能上很類似。
模板方法模式主要是用來定義算法的骨架,把算法中某些步驟延遲到子類中實現(xiàn)。再想想生成器模式,Director用來定義整體的構(gòu)建算法,把算法中某些涉及到具體部件對象的創(chuàng)建和裝配的功能,委托給具體的Builder來實現(xiàn)。
雖然生成器不是延遲到子類,是委托給Builder,但那只是具體實現(xiàn)方式上的差別,從實質(zhì)上看兩個模式很類似,都是定義一個固定的算法骨架,然后把算法中的某些具體步驟交給其它類來完成,都能實現(xiàn)整體算法步驟和某些具體步驟實現(xiàn)的分離。
當然兩個模式也有很大的區(qū)別,首先是模式的目的,生成器模式是用來構(gòu)建復(fù)雜對象的,而模板方法是用來定義算法骨架,尤其是一些復(fù)雜的業(yè)務(wù)功能的處理算法的骨架;其次是模式的實現(xiàn),生成器模式是采用委托的方法,而模板方法是采用的繼承的方式;另外從使用的復(fù)雜度上,生成器模式需要組合Director和Builder對象,然后才能開始構(gòu)建,要等構(gòu)建完后才能獲得最終的對象,而模板方法就沒有這么麻煩,直接使用子類對象即可。
7.4 生成器模式和組合模式
這兩個模式可以組合使用。
對于復(fù)雜的組合結(jié)構(gòu),可以使用生成器模式來一步一步構(gòu)建。
8.原型模式的相關(guān)模式
8.1 原型模式和抽象工廠模式
功能上有些相似,都是用來獲取一個新的對象實例的。
不同之處在于,原型模式的著眼點是在如何創(chuàng)造出實例對象來,最后選擇的方案是通過克?。欢橄蠊S模式的著眼點則在于如何來創(chuàng)造產(chǎn)品簇,至于具體如何創(chuàng)建出產(chǎn)品簇中的每個對象實例,抽象工廠模式不是很關(guān)注。
正是因為它們的關(guān)注點不一樣,所以它們也可以配合使用,比如在抽象工廠模式里面,具體創(chuàng)建每一種產(chǎn)品的時候就可以使用該種產(chǎn)品的原型,也就是抽象工廠管產(chǎn)品簇,具體的每種產(chǎn)品怎么創(chuàng)建則可以選擇原型模式。
8.2 原型模式和生成器模式
這兩種模式可以配合使用。
生成器模式關(guān)注的是構(gòu)建的過程,而在構(gòu)建的過程中,很可能需要某個部件的實例,那么很自然地就可以應(yīng)用上原型模式,通過原型模式來得到部件的實例。
9.中介者模式的相關(guān)模式
9.1 中介者模式和外觀模式
這兩個模式有相似的地方,也存在很大的不同。
外觀模式多用來封裝一個子系統(tǒng)內(nèi)部的多個模塊,目的是向子系統(tǒng)外部提供簡單易用的接口,也就是說外觀模式封裝的是子系統(tǒng)外部和子系統(tǒng)內(nèi)部模塊間的交互;而中介者模式是提供多個平等的同事對象之間交互關(guān)系的封裝,一般是用在內(nèi)部實現(xiàn)上。
另外,外觀模式是實現(xiàn)單向的交互,是從子系統(tǒng)外部來調(diào)用子系統(tǒng)內(nèi)部,不會反著來,而中介者模式實現(xiàn)的是內(nèi)部多個模塊間多向的交互。
9.2 中介者模式和觀察者模式
這兩個模式可以組合使用。
中介者模式可以組合使用觀察者模式,來實現(xiàn)當同事對象發(fā)生改變的時候,通知中介對象,讓中介對象去進行與其它相關(guān)對象的交互。
10.代理模式的相關(guān)模式
10.1 代理模式和適配器模式
這兩個模式有一定的相似性,但也有差異。
這兩個模式有相似性,它們都為另一個對象提供間接性的訪問,而且都是從自身以外的一個接口向這個對象轉(zhuǎn)發(fā)請求。
但是從功能上,兩個模式是不一樣的。適配器模式主要用來解決接口之間不匹配的問題,它通常是為所適配的對象提供一個不同的接口;而代理模式會實現(xiàn)和目標對象相同的接口。
10.2 代理模式和裝飾模式
這兩個模式從實現(xiàn)上相似,但是功能上是不同的。
裝飾模式的實現(xiàn)和保護代理的實現(xiàn)上是類似的,都是在轉(zhuǎn)調(diào)其它對象的前后執(zhí)行一定的功能。但是它們的目的和功能都是不同的。
裝飾模式的目的是為了讓你不生成子類就可以給對象添加職責,也就是為了動態(tài)的增加功能;而代理模式的主要目的是控制對對象的訪問。
11.觀察者模式的相關(guān)模式
11.1 觀察者模式和狀態(tài)模式
觀察者模式和狀態(tài)模式是有相似之處的。
觀察者模式是當目標狀態(tài)發(fā)生改變時,觸發(fā)并通知觀察者,讓觀察者去執(zhí)行相應(yīng)的操作。而狀態(tài)模式是根據(jù)不同的狀態(tài),選擇不同的實現(xiàn),這個實現(xiàn)類的主要功能就是針對狀態(tài)的相應(yīng)的操作,它不像觀察者,觀察者本身還有很多其它的功能,接收通知并執(zhí)行相應(yīng)處理只是觀察者的部分功能。
當然觀察者模式和狀態(tài)模式是可以結(jié)合使用的。觀察者模式的重心在觸發(fā)聯(lián)動,但是到底決定哪些觀察者會被聯(lián)動,這時就可以采用狀態(tài)模式來實現(xiàn)了,也可以采用策略模式來進行選擇需要聯(lián)動的觀察者。
11.2 觀察者模式和中介者模式
觀察者模式和中介者模式是可以結(jié)合使用的。
前面的例子中目標都只是簡單的通知一下,然后讓各個觀察者自己去完成更新就結(jié)束了。如果觀察者和被觀察的目標之間的交互關(guān)系很復(fù)雜,比如:有一個界面,里面有三個下拉列表組件,分別是選擇國家、省份/州、具體的城市,很明顯這是一個三級聯(lián)動,當你選擇一個國家的時候,省份/州應(yīng)該相應(yīng)改變數(shù)據(jù),省份/州一改變,具體的城市也需要改變。
這種情況下,很明顯需要相關(guān)的狀態(tài)都聯(lián)動準備好了,然后再一次性的通知觀察者,就是界面做更新處理,不會國家改變一下,省份和城市還沒有改,就通知界面更新。這種情況就可以使用中介者模式來封裝觀察者和目標的關(guān)系。
在使用Swing的小型應(yīng)用里面,也可以使用中介者模式。比如:把一個界面所有的事件用一個對象來處理,把一個組件觸發(fā)事件過后,需要操作其它組件的動作都封裝到一起,這個對象就是典型的中介者。
12.命令模式的相關(guān)模式
12.1 命令模式和組合模式
這兩個模式可以組合使用。
在命令模式中,實現(xiàn)宏命令的功能,就可以使用組合模式來實現(xiàn)。前面的示例并沒有按照組合模式來做,那是為了保持示例的簡單,還有突出命令模式的實現(xiàn),這點請注意。
12.2 命令模式和備忘錄模式
這兩個模式可以組合使用。
在命令模式中,實現(xiàn)可撤銷操作功能時,前面講了有兩種實現(xiàn)方式,其中有一種就是保存命令執(zhí)行前的狀態(tài),撤銷的時候就把狀態(tài)恢復(fù)回去。如果采用這種方式實現(xiàn),就可以考慮使用備忘錄模式。
如果狀態(tài)存儲在命令對象里面,那么還可以使用原型模式,把命令對象當作原型來克隆一個新的對象,然后把克隆出來的對象通過備忘錄模式存放。
12.3 命令模式和模板方法模式
這兩個模式從某種意義上有相似的功能,命令模式可以作為模板方法的一種替代模式,也就是說命令模式可以模仿實現(xiàn)模板方法模式的功能。
如同前面講述的退化的命令模式可以實現(xiàn)Java的回調(diào),而Invoker智能化后向服務(wù)進化,如果Invoker的方法就是一個算法骨架,其中有兩步在這個骨架里面沒有具體實現(xiàn),需要外部來實現(xiàn),這個時候就可以通過回調(diào)命令接口來實現(xiàn)。而類似的功能在模板方法里面,一個算法骨架,其中有兩步在這個骨架里面沒有具體實現(xiàn),是先調(diào)用抽象方法,然后等待子類來實現(xiàn)。
可以看出雖然實現(xiàn)方式不一樣,但是可以實現(xiàn)相同的功能。
13.迭代器模式的相關(guān)模式
13.1 迭代器模式和組合模式
這兩個模式可以組合使用。
組合模式是一種遞歸的對象結(jié)構(gòu),在枚舉某個組合對象的子對象的時候,通常會使用迭代器模式。
13.2 迭代器模式和工廠方法模式
這兩個模式可以組合使用。
在聚合對象創(chuàng)建迭代器的時候,通常會采用工廠方法模式來實例化相應(yīng)的迭代器對象。
14.組合模式的相關(guān)模式
14.1 組合模式和裝飾模式
這兩個模式可以組合使用。
裝飾模式在組裝多個裝飾器對象的時候,是一個裝飾器找下一個裝飾器,下一個再找下一個,如此遞歸下去。那么這種結(jié)構(gòu)也可以使用組合模式來幫助構(gòu)建,這樣一來,裝飾器對象就相當于組合模式的Composite對象了。
要讓兩個模式能很好的組合使用,通常會讓它們有一個公共的父類,因此裝飾器必須支持組合模式需要的一些功能,比如:增加、刪除子組件等等。
14.2 組合模式和享元模式
這兩個模式可以組合使用。
如果組合模式中出現(xiàn)大量相似的組件對象的話,可以考慮使用享元模式來幫助緩存組件對象,這可以減少對內(nèi)存的需要。
使用享元模式也是有條件的,如果組件對象的可變化部分的狀態(tài)能夠從組件對象里面分離出去,而且組件對象本身不需要向父組件發(fā)送請求的話,就可以采用享元模式。
14.3 組合模式和迭代器模式
這兩個模式可以組合使用。
在組合模式中,通??梢允褂玫髂J絹肀闅v組合對象的子對象集合,而無需關(guān)心具體存放子對象的聚合結(jié)構(gòu)。
14.4 組合模式和訪問者模式
這兩個模式可以組合使用。
訪問者模式能夠在不修改原有對象結(jié)構(gòu)的情況下,給對象結(jié)構(gòu)中的對象增添新的功能。將訪問者模式和組合模式合用,可以把原本分散在Composite和 Leaf類中的操作和行為都局部化。
如果在使用組合模式的時候,預(yù)計到今后可能會有增添其它功能的可能,那么可以采用訪問者模式,來預(yù)留好添加新功能的方式和通道,這樣以后在添加新功能的時候,就不需要再修改已有的對象結(jié)構(gòu)和已經(jīng)實現(xiàn)的功能了。
14.5 組合模式和職責鏈模式
這兩個模式可以組合使用。
職責鏈模式要解決的問題是:實現(xiàn)請求的發(fā)送者和接收者之間解耦。職責鏈模式的實現(xiàn)方式是把多個接收者組合起來,構(gòu)成職責鏈,然后讓請求在這條鏈上傳遞,直到有接收者處理這個請求為止。
可以應(yīng)用組合模式來構(gòu)建這條鏈,相當于是子組件找父組件,父組件又找父組件,如此遞歸下去,構(gòu)成一條處理請求的組件對象鏈。
14.6 組合模式和命令模式
這兩個模式可以組合使用。
命令模式中有一個宏命令的功能,通常這個宏命令就是使用組合模式來組裝出來的。
15.模板方法模式的相關(guān)模式
15.1 模板方法模式和工廠方法模式
這兩個模式可以配合使用。
模板方法模式可以通過工廠方法來獲取需要調(diào)用的對象。
15.2 模板方法模式和策略模式
這兩個模式的功能有些相似,但是是有區(qū)別的。
從表面上看,兩個模式都能實現(xiàn)算法的封裝,但是模板方法封裝的是算法的骨架,這個算法骨架是不變的,變化的是算法中某些步驟的具體實現(xiàn);而策略模式是把某個步驟的具體實現(xiàn)算法封裝起來,所有封裝的算法對象是等價的,可以相互替換。
因此,可以在模板方法中使用策略模式,就是把那些變化的算法步驟通過使用策略模式來實現(xiàn),但是具體選取哪個策略還是要由外部來確定,而整體的算法步驟,也就是算法骨架就由模板方法來定義了。
16.策略模式的相關(guān)模式
16.1 策略模式和狀態(tài)模式
這兩個模式從模式結(jié)構(gòu)上看是一樣的,但是實現(xiàn)的功能是不一樣的。
狀態(tài)模式是根據(jù)狀態(tài)的變化來選擇相應(yīng)的行為,不同的狀態(tài)對應(yīng)不同的類,每個狀態(tài)對應(yīng)的類實現(xiàn)了該狀態(tài)對應(yīng)的功能,在實現(xiàn)功能的同時,還會維護狀態(tài)數(shù)據(jù)的變化。這些實現(xiàn)狀態(tài)對應(yīng)的功能的類之間是不能相互替換的。策略模式是根據(jù)需要或者是客戶端的要求來選擇相應(yīng)的實現(xiàn)類,各個實現(xiàn)類是平等的,是可以相互替換的。
另外策略模式可以讓客戶端來選擇需要使用的策略算法,而狀態(tài)模式一般是由上下文,或者是在狀態(tài)實現(xiàn)類里面來維護具體的狀態(tài)數(shù)據(jù),通常不由客戶端來指定狀態(tài)。
16.2 策略模式和模板方法模式
這兩個模式可組合使用,如同前面示例的那樣。
模板方法重在封裝算法骨架,而策略模式重在分離并封裝算法實現(xiàn)。
16.3 策略模式和享元模式
這兩個模式可組合使用。
策略模式分離并封裝出一系列的策略算法對象,這些對象的功能通常都比較單一,很多時候就是為了實現(xiàn)某個算法的功能而存在,因此,針對這一系列的、多個細粒度的對象,可以應(yīng)用享元模式來節(jié)省資源,但前提是這些算法對象要被頻繁的使用,如果偶爾用一次,就沒有必要做成享元了。
17.狀態(tài)模式的相關(guān)模式
17.1 狀態(tài)模式和觀察者模式
這兩個模式乍一看,功能是很相似的,但是又有區(qū)別,可以組合使用。
模式都是在狀態(tài)發(fā)生改變的時候觸發(fā)行為,只不過觀察者模式的行為是固定的,那就是通知所有的觀察者,而狀態(tài)模式是根據(jù)狀態(tài)來選擇不同的處理。
從表面來看兩個模式功能相似,觀察者中的被觀察對象就好比狀態(tài)模式中的上下文,觀察者模式中當被觀察對象的狀態(tài)發(fā)生改變的時候,觸發(fā)的通知所有觀察者的方法;就好比狀態(tài)模式中,根據(jù)狀態(tài)的變化,選擇對應(yīng)的狀態(tài)處理。
但實際這兩個模式是不同的,觀察者模式的目的是在被觀察者的狀態(tài)發(fā)生改變的時候,觸發(fā)觀察者聯(lián)動,具體如何處理觀察者模式不管;而狀態(tài)模式的主要目的在于根據(jù)狀態(tài)來分離和選擇行為,當狀態(tài)發(fā)生改變的時候,動態(tài)改變行為。
這兩個模式是可以組合使用的,比如在觀察者模式的觀察者部分,當被觀察對象的狀態(tài)發(fā)生了改變,觸發(fā)通知了所有的觀察者過后,觀察者該怎么處理呢?這個時候就可以使用狀態(tài)模式,根據(jù)通知過來的狀態(tài)選擇相應(yīng)的處理。
17.2 狀態(tài)模式和策略模式
這是兩個結(jié)構(gòu)相同,功能各異的模式,具體的在策略模式里面講過了,這里不再贅述。
17.3 狀態(tài)模式和單例模式
這兩個模式可以組合使用,可以把狀態(tài)模式中的狀態(tài)處理類實現(xiàn)成單例。
17.4 狀態(tài)模式和享元模式
這兩個模式可以組合使用。
由于狀態(tài)模式把狀態(tài)對應(yīng)的行為分散到多個狀態(tài)對象中,會造成很多細粒度的狀態(tài)對象,可以把這些狀態(tài)處理對象通過享元模式來共享,從而節(jié)省資源。
18.備忘錄模式的相關(guān)模式
18.1 備忘錄模式和命令模式
這兩個模式可以組合使用。
命令模式實現(xiàn)中,在實現(xiàn)命令的撤銷和重做的時候,可以使用備忘錄模式,在命令操作的時候記錄下操作前后的狀態(tài),然后在命令撤銷和重做的時候,直接使用相應(yīng)的備忘錄對象來恢復(fù)狀態(tài)就可以了。
在這種撤銷的執(zhí)行順序和重做執(zhí)行順序可控的情況下,備忘錄對象還可以采用增量式記錄的方式,可以減少緩存的數(shù)據(jù)量。
18.2 備忘錄模式和原型模式
這兩個模式可以組合使用。
在原發(fā)器對象創(chuàng)建備忘錄對象的時候,如果原發(fā)器對象中全部或者大部分的狀態(tài)都需要保存,一個簡潔的方式就是直接克隆一個原發(fā)器對象。也就是說,這個時候備忘錄對象里面存放的是一個原發(fā)器對象的實例,這個在前面已經(jīng)示例過了,這里就不贅述了。
19.享元模式的相關(guān)模式
19.1 享元模式與單例模式
這兩個模式可以組合使用。
通常情況下,享元模式中的享元工廠可以實現(xiàn)成為單例。另外,享元工廠里面緩存的享元對象,都是單實例的,可以看成是單例模式的一種變形控制,在享元工廠里面來單例享元對象。
19.2 享元模式與組合模式
這兩個模式可以組合使用。
在享元模式里面,存在不需要共享的享元實現(xiàn),這些不需要共享的享元通常是對共享的享元對象的組合對象,也就是說,享元模式通常會和組合模式組合使用,來實現(xiàn)更復(fù)雜的對象層次結(jié)構(gòu)。
19.3 享元模式與狀態(tài)模式
這兩個模式可以組合使用。
可以使用享元模式來共享狀態(tài)模式中的狀態(tài)對象,通常在狀態(tài)模式中,會存在數(shù)量很大的、細粒度的狀態(tài)對象,而且它們基本上都是可以重復(fù)使用的,都是用來處理某一個固定的狀態(tài)的,它們需要的數(shù)據(jù)通常都是由上下文傳入,也就是變化部分都分離出去了,所以可以用享元模式來實現(xiàn)這些狀態(tài)對象。
19.4 享元模式與策略模式
這兩個模式可以組合使用。
可以使用享元模式來實現(xiàn)策略模式中的策略對象,跟狀態(tài)模式一樣,在策略模式中也存在大量細粒度的策略對象,它們需要的數(shù)據(jù)同樣是從上下文傳入的,所以可以使用享元模式來實現(xiàn)這些策略對象
20.解釋器模式的相關(guān)模式
20.1 解釋器模式和組合模式
這兩個模式可以組合使用。
通常解釋器模式都會使用組合模式來實現(xiàn),這樣能夠方便的構(gòu)建抽象語法樹。一般非終結(jié)符解釋器就相當于組合模式中的組合對象,終結(jié)符解釋器就相當于葉子對象。
20.2 解釋器模式和迭代器模式
這兩個模式可以組合使用。
由于解釋器模式通常使用組合模式來實現(xiàn),因此在遍歷整個對象結(jié)構(gòu)的時候,自然可以使用迭代器模式。
20.3 解釋器模式和享元模式
這兩個模式可以組合使用。
在使用解釋器模式的時候,可能會造成多個細粒度對象,比如會有各種各樣的終結(jié)符解釋器,而這些終結(jié)符解釋器對不同的表達式來說是一樣的,是可以共用的,因此可以引入享元模式來共享這些對象。
20.4 解釋器模式和訪問者模式
這兩個模式可以組合使用。
在解釋器模式中,語法規(guī)則和解釋器對象是有對應(yīng)關(guān)系的。語法規(guī)則的變動意味著功能的變化,自然會導(dǎo)致使用不同的解釋器對象;而且一個語法規(guī)則可以被不同的解釋器解釋執(zhí)行。
因此在構(gòu)建抽象語法樹的時候,如果每個節(jié)點所對應(yīng)的解釋器對象是固定的,這就意味著這個節(jié)點對應(yīng)的功能是固定的,那么就不得不根據(jù)需要來構(gòu)建不同的抽象語法樹。
為了讓構(gòu)建的抽象語法樹較為通用,那就要求解釋器的功能不要那么固定,要能很方便的改變解釋器的功能,這個時候問題就變成了,如何能夠很方便的更改樹形結(jié)構(gòu)中節(jié)點對象的功能了,訪問者模式可以很好的實現(xiàn)這個功能。
21.裝飾模式的相關(guān)模式
21.1 裝飾模式與適配器模式
這是兩個沒有什么關(guān)聯(lián)的模式,放到一起來說,是因為它們有一個共同的別名:Wrapper。
這兩個模式功能上是不一樣的,適配器模式是用來改變接口的,而裝飾模式是用來改變對象功能的。
21.2 裝飾模式與組合模式
這兩個模式有相似之處,都涉及到對象的遞歸調(diào)用,從某個角度來說,可以把裝飾看成是只有一個組件的組合。
但是它們的目的完全不一樣,裝飾模式是要動態(tài)的給對象增加功能;而組合模式是想要管理組合對象和葉子對象,為它們提供一個一致的操作接口給客戶端,方便客戶端的使用。
21.3 裝飾模式與策略模式
這兩個模式可以組合使用。
策略模式也可以實現(xiàn)動態(tài)的改變對象的功能,但是策略模式只是一層選擇,也就是根據(jù)策略選擇一下具體的實現(xiàn)類而已。而裝飾模式不是一層,而是遞歸調(diào)用,無數(shù)層都可以,只要組合好裝飾器的對象組合,那就可以依次調(diào)用下去,所以裝飾模式會更靈活。
而且策略模式改變的是原始對象的功能,不像裝飾模式,后面一個裝飾器,改變的是經(jīng)過前一個裝飾器裝飾過后的對象,也就是策略模式改變的是對象的內(nèi)核,而裝飾模式改變的是對象的外殼。
這兩個模式可以組合使用,可以在一個具體的裝飾器里面使用策略模式,來選擇更具體的實現(xiàn)方式。比如前面計算獎金的另外一個問題就是參與計算的基數(shù)不同,獎金的計算方式也是不同的。舉例來說:假設(shè)張三和李四參與同一個獎金的計算,張三的銷售總額是2萬元,而李四的銷售額是8萬元,它們的計算公式是不一樣的,假設(shè)獎金的計算規(guī)則是,銷售額在5萬以下,統(tǒng)一3%,而5萬以上,5萬內(nèi)是4%,超過部分是6%。
參與同一個獎金的計算,這就意味著可以使用同一個裝飾器,但是在裝飾器的內(nèi)部,不同條件下計算公式不一樣,那么怎么選擇具體的實現(xiàn)策略呢?自然使用策略模式就好了,也就是裝飾模式和策略模式組合來使用。
21.4 裝飾模式與模板方法模式
這是兩個功能上有相似點的模式。
模板方法模式主要應(yīng)用在算法骨架固定的情況,那么要是算法步驟不固定呢,也就是一個相對動態(tài)的算法步驟,就可以使用裝飾模式了,因為在使用裝飾模式的時候,進行裝飾器的組裝,其實也相當于是一個調(diào)用算法步驟的組裝,相當于是一個動態(tài)的算法骨架。
既然裝飾模式可以實現(xiàn)動態(tài)的算法步驟的組裝和調(diào)用,那么把這些算法步驟固定下來,那就是模板方法模式實現(xiàn)的功能了,因此裝飾模式可以模擬實現(xiàn)模板方法模式的功能。
但是請注意,僅僅只是可以模擬功能而已,兩個模式的設(shè)計目的、原本的功能、本質(zhì)思想等都是不一樣的。
22.職責鏈模式的相關(guān)模式
22.1 職責鏈模式和組合模式
這兩個模式可以組合使用。
可以把職責對象通過組合模式來組合,這樣可以通過組合對象自動遞歸的向上調(diào)用,由父組件作為子組件的后繼,從而形成鏈。這也就是前面提到過的使用外部已有的鏈接,這種情況在客戶端使用的時候,就不用再構(gòu)造鏈了,雖然不構(gòu)造鏈,但是需要構(gòu)造組合對象樹,是一樣的。
22.2 職責鏈模式和策略模式
這兩個模式可以組合使用。
這兩個模式有相似之處,如果把職責鏈簡化到直接就能選擇到相應(yīng)的處理對象,那就跟策略模式的選擇差不多,因此可以用職責鏈來模擬策略模式的功能。只是如果把職責鏈簡化到這個地步,也就不存在鏈了,也就稱不上是職責鏈了。
兩個模式可以組合使用,可以在職責鏈模式的某個職責的實現(xiàn)的時候,使用策略模式來選擇具體的實現(xiàn),同樣也可以在策略模式的某個策略實現(xiàn)里面,使用職責鏈模式來實現(xiàn)功能處理。
同理職責鏈模式也可以和狀態(tài)模式組合使用。
22.3 職責鏈模式和裝飾模式
這兩個模式相似,從某個角度講,可以相互模擬實現(xiàn)對方的功能。
裝飾模式能夠動態(tài)的給被裝飾對象添加功能,要求裝飾器對象和被裝飾的對象實現(xiàn)相同的接口。而職責鏈模式可以實現(xiàn)動態(tài)的職責組合,標準的功能是有一個對象處理就結(jié)束,但是如果處理完本職責不急于結(jié)束,而是繼續(xù)向下傳遞請求,那么功能就和裝飾模式的功能差不多了,每個職責對象就類似于裝飾器,可以實現(xiàn)某種功能。
而且兩個模式的本質(zhì)也類似,都需要在運行期間動態(tài)組合,裝飾模式是動態(tài)組合裝飾器,而職責鏈是動態(tài)組合處理請求的職責對象的鏈。
但是從標準的設(shè)計模式上來講,這兩個模式還是有較大區(qū)別的,這點要注意。首先是目的不同,裝飾模式是要實現(xiàn)透明的為對象添加功能,而職責鏈模式是要實現(xiàn)發(fā)送者和接收者解耦;另外一個,裝飾模式是無限遞歸調(diào)用的,可以有任意多個對象來裝飾功能,但是職責鏈模式是有一個處理就結(jié)束。
23.橋接模式的相關(guān)模式
23.1 橋接模式和策略模式
這兩個模式有很大的相似之處。
如果把橋接模式的抽象部分簡化來看,如果暫時不去擴展Abstraction,也就是去掉 RefinedAbstraction。會發(fā)現(xiàn),這個時候它們的結(jié)構(gòu)都類似如圖所示:
通過上面的結(jié)構(gòu)圖,可以體會到橋接模式和策略模式是如此相似。可以把策略模式的Context視做是使用接口的對象,而Strategy就是某個接口了,具體的策略實現(xiàn)那就相當于接口的具體實現(xiàn)。這樣看來的話,某些情況下,可以使用橋接模式來模擬實現(xiàn)策略模式的功能。
這兩個模式雖然相似,也還是有區(qū)別的。最主要的是模式的目的不一樣,策略模式的目的是封裝一系列的算法,使得這些算法可以相互替換;而橋接模式的目的是分離抽象和實現(xiàn)部分,使得它們可以獨立的變化。
23.2 橋接模式和狀態(tài)模式
由于從模式結(jié)構(gòu)上看,狀態(tài)模式和策略模式是一樣的,這兩個模式的關(guān)系也基本上類似于橋接模式和策略模式的關(guān)系。
只不過狀態(tài)模式的目的是封裝狀態(tài)對應(yīng)的行為,并在內(nèi)部狀態(tài)改變的時候改變對象的行為。
23.3 橋接模式和抽象工廠模式
這兩個模式可以組合使用。
橋接模式中,抽象部分需要獲取相應(yīng)的實現(xiàn)部分的接口對象,那么誰來創(chuàng)建實現(xiàn)部分的具體實現(xiàn)對象呢?這就是抽象工廠模式派上用場的地方。也就是使用抽象工廠模式來創(chuàng)建和配置一個特定的具體實現(xiàn)的對象。
事實上,抽象工廠主要是用來創(chuàng)建一系列對象的,如果創(chuàng)建的對象很少,或者是很簡單,還可以采用簡單工廠,可以達到一樣的效果,但是會比抽象工廠來得簡單。
23.4 橋接模式和模板方法模式
這兩個模式有相似之處。
雖然標準的模板方法模式是采用繼承來實現(xiàn)的,但是模板方法也可以通過回調(diào)接口的方式來實現(xiàn),如果把接口的實現(xiàn)獨立出去,那就類似于模板方法通過接口去調(diào)用具體的實現(xiàn)方法了。這樣的結(jié)構(gòu)就和簡化的橋接模式類似了。
可以使用橋接模式來模擬實現(xiàn)模板方法模式的功能。如果在實現(xiàn)Abstraction對象的時候,在里面定義方法,方法里面就是某個固定的算法骨架,也就是說這個方法就相當于模板方法。在模板方法模式里,是把不能確定實現(xiàn)的步驟延遲到子類去實現(xiàn);現(xiàn)在在橋接模式里面,把不能確定實現(xiàn)的步驟委托給具體實現(xiàn)部分去完成,通過回調(diào)實現(xiàn)部分的接口,來完成算法骨架中的某些步驟。這樣一來,就可以實現(xiàn)使用橋接模式來模擬實現(xiàn)模板方法模式的功能了。
使用橋接模式來模擬實現(xiàn)模板方法模式的功能,還有個潛在的好處,就是模板方法也可以很方便的擴展和變化了。在標準的模板方法里面,一個問題就是當模板發(fā)生變化的時候,所有的子類都要變化,非常不方便。而使用橋接模式來實現(xiàn)類似的功能,就沒有這個問題了。
另外,這里只是說從實現(xiàn)具體的業(yè)務(wù)功能上,橋接模式可以模擬實現(xiàn)出模板方法模式能實現(xiàn)的功能,并不是說橋接模式和模板方法模式就變成一樣的,或者是橋接模式就可以替換掉模板方法模式了。要注意它們本身的功能、目的、本質(zhì)思想都是不一樣的。
23.5 橋接模式和適配器模式
這兩個模式可以組合使用。
這兩個模式功能是完全不一樣的,適配器模式的功能主要是用來幫助無關(guān)的類協(xié)同工作,重點在解決原本由于接口不兼容而不能一起工作的那些類,使得它們可以一起工作。而橋接模式則重點在分離抽象和實現(xiàn)部分。
所以在使用上,通常在系統(tǒng)設(shè)計完成過后,才會考慮使用適配器模式;而橋接模式,是在系統(tǒng)開始的時候就要考慮使用。
雖然功能上不一樣,這兩個模式還是可以組合使用的,比如:已有實現(xiàn)部分的接口,但是有些不太適應(yīng)現(xiàn)在新的功能對接口的需要,完全拋棄吧,有些功能還用得上,該怎么辦呢?那就使用適配器來進行適配,使得舊的接口能夠適應(yīng)新的功能的需要。
24.訪問者模式的相關(guān)模式
24.1 訪問者模式和組合模式
這兩個模式可以組合使用。
如同前面示例的那樣,通過訪問者模式給組合對象預(yù)留下擴展功能的接口,使得給組合模式的對象結(jié)構(gòu)添加功能非常容易。
24.2 訪問者模式和裝飾模式
這兩個模式從表面看功能有些相似,都能夠?qū)崿F(xiàn)在不修改原對象結(jié)構(gòu)的情況下修改原對象的功能。但是裝飾模式更多的是實現(xiàn)對已有功能加強、或者修改、或者完全全新實現(xiàn);而訪問者模式更多的是實現(xiàn)給對象結(jié)構(gòu)添加新的功能。
24.3 訪問者模式和解釋器模式
這兩個模式可以組合使用。
解釋器模式在構(gòu)建抽象語法樹的時候,是使用組合模式來構(gòu)建的,也就是說解釋器模式解釋并執(zhí)行的抽象語法樹是一個組合對象結(jié)構(gòu),這個組合對象結(jié)構(gòu)是很少變動的,但是可能經(jīng)常需要為解釋器增加新的功能,實現(xiàn)對同一對象結(jié)構(gòu)的不同解釋和執(zhí)行的功能,這正好是訪問者模式的優(yōu)勢所在,因此這在使用解釋器模式的時候通常會組合訪問者模式來使用。
后續(xù)應(yīng)該做的事
不是結(jié)束而是新的開始。并不是說你就不用再學(xué)習(xí)設(shè)計模式了,恰恰相反,要想在設(shè)計上更進一步的話,困難才剛剛開始。從中級的水平向上發(fā)展,更多的是需要思考和領(lǐng)悟,其難度比從入門到中級要大得多。因此對你而言,學(xué)到這里并不是學(xué)習(xí)的結(jié)束,而是新的開始。
你該怎么做
- 1)多看
多搜尋一些應(yīng)用設(shè)計模式的實際項目、工程或是框架,參考別人的成功應(yīng)用,再結(jié)合自己的經(jīng)驗來思考和使用。當然項目不應(yīng)該太大,太大了很難完全看懂;也不能太小,太小了,沒有太大實用價值,尤其是無法參考多個模式綜合應(yīng)用的情況,幫助就不大了。 - 2)多練
多尋找機會,把這些設(shè)計模式在實際應(yīng)用中使用,只有親自動手去試驗和使用,才能真正掌握和領(lǐng)會設(shè)計模式的精髓。 - 3)多總結(jié):認真分析每次對設(shè)計模式的使用是否得當,有什么經(jīng)驗和教訓(xùn),是否有變形使用的情況,在不斷總結(jié)中進步。
- 4)反復(fù)參閱《研磨設(shè)計模式》一書:理論聯(lián)系實際,通過實際應(yīng)用反過來加深對理論的理解,以達到融會貫通這些設(shè)計模式的知識。因此,你需要反復(fù)參閱《研磨設(shè)計模式》一書,看看書上的知識,然后實踐,然后再回頭看書上的知識,你會有不一樣的體會和領(lǐng)悟。
- 5)多思考:多從設(shè)計上去思考這些設(shè)計模式,考慮它的設(shè)計意圖、設(shè)計思想、解決問題的方式、實現(xiàn)的原理、模式的本質(zhì)、以及如何變形使用等等。只要你堅持去按照上面說的做,假以時日,必有所成。