相關模式辨析

0.提前說明

  • 模式選擇的方法
    1)模式的功能——看是否能解決問題
    2)模式的本質——看模式是否主要用來解決這類問題
    3)模式的適用程度——看使用這個模式是否貼切,看是否需要變形
    4)應用模式的復雜程度——看使用模式帶來的開發復雜度是否可接受或可控
    5)應用模式的代價——看使用模式的代價是否可接受或可控,如:引入過多的對象、耗費更多的內存等

  • 很多模式都可以組合使用,并不局限于這里要講的

  • 有些模式功能相近,結構類似,要特別注意他們的辨析

  • 掌握模式一定要從思想上、本質上、整體上去把握

1. 簡單工廠的相關模式

1.1 簡單工廠和抽象工廠模式

簡單工廠是用來選擇實現的,可以選擇任意接口的實現,一個簡單工廠可以有多個用于選擇并創建對象的方法,多個方法創建的對象可以有關系也可以沒有關系。

抽象工廠模式是用來選擇產品簇的實現的,也就是說一般抽象工廠里面有多個用于選擇并創建對象的方法,但是這些方法所創建的對象之間通常是有關系的,這些被創建的對象通常是構成一個產品簇所需要的部件對象。

所以從某種意義上來說,簡單工廠和抽象工廠是類似的,如果抽象工廠退化成為只有一個實現,不分層次,那么就相當于簡單工廠了。

1.2 簡單工廠和工廠方法模式

簡單工廠和工廠方法模式也是非常類似的。

工廠方法的本質也是用來選擇實現的,跟簡單工廠的區別在于工廠方法是把選擇具體實現的功能延遲到子類去實現。

如果把工廠方法中選擇的實現放到父類直接實現,那就等同于簡單工廠

1.3 簡單工廠和能創建對象實例的模式

簡單工廠的本質是選擇實現,所以它可以跟其它任何能夠具體的創建對象實例的模式配合使用,比如:單例模式、原型模式、生成器模式等等。

2.外觀模式的相關模式

2.1 外觀模式和中介者模式

這兩個模式非常類似,但是有本質的區別。

中介者模式主要用來封裝多個對象之間相互的交互,多用在系統內部的多
個模塊之間;而外觀模式封裝的是單向的交互,是從客戶端訪問系統的調用,沒有從系統中來訪問客戶端的調用。

在中介者模式的實現里面,是需要實現具體的交互功能的;而外觀模式的實現里面,一般是組合調用或是轉調內部實現的功能,通常外觀模式本身并不實現這些功能。

中介者模式的目的主要是松散多個模塊之間的耦合,把這些耦合關系全部放到中介者中去實現;而外觀模式的目的是簡化客戶端的調用,這點和中介者模式也不同。

2.2 外觀模式和單例模式

通常一個子系統只需要一個外觀實例,所以外觀模式可以和單例模式組合使用,把Facade類實現成為單例。當然,也可以跟前面示例的那樣,把外觀類的構造方法私有化,然后把提供給客戶端的方法實現成為靜態的

2.3 外觀模式和抽象工廠模式

外觀模式的外觀類通常需要和系統內部的多個模塊交互,每個模塊一般都有自己的接口,所以在外觀類的具體實現里面,需要獲取這些接口,然后組合這些接口來完成客戶端的功能。

那么怎么獲取這些接口呢?就可以和抽象工廠一起使用,外觀類通過抽象工廠來獲取所需要的接口,而抽象工廠也可以把模塊內部的實現對Facade進行屏蔽,也就是說Facade也僅僅只是知道它從模塊中獲取的它需要的功能,模塊內部的細節,Facade也不知道了。

3.適配器模式的相關模式

3.1 適配器模式與橋接模式

其實這兩個模式除了結構略為相似外,功能上完全不同。

適配器模式是把兩個或者多個接口的功能進行轉換匹配;而橋接模式是讓接口和實現部分相分離,以便它們可以相對獨立的變化。

3.2 適配器模式與裝飾模式

從某種意義上講,適配器模式能模擬實現簡單的裝飾模式的功能,也就是為已有功能增添功能。

造成這種類似的原因:兩種設計模式在實現上都是使用的對象組合,都可以在轉調組合對象的功能前后進行一些附加的處理,因此有這么一個相似性。它們的目的和本質都是不一樣的。

兩個模式有一個很大的不同:一般適配器適配過后是需要改變接口的,如果不改接口就沒有必要適配了;而裝飾模式是不改接口的,無論多少層裝飾都是一個接口。

因此裝飾模式可以很容易的支持遞歸組合,而適配器就做不到了,每次的接口不同,沒法遞歸。

3.3 適配器模式和代理模式

適配器模式可以跟代理模式組合使用,在實現適配器的時候,可以通過代理來調用Adaptee,這可以獲得更大的靈活性

3.4 適配器模式和抽象工廠模式

在適配器實現的時候,通常需要得到被適配的對象,如果被適配的是一個接口,那么就可以結合一些可以創造對象實例的設計模式,來得到被適配的對象示例。比如:抽象工廠模式、單例模式、工廠方法模式等

4.單例模式的相關模式

很多模式都可以使用單例模式,只要這些模式中的某個類,需要控制實例為一個的時候,就可以很自然的使用上單例模式。比如抽象工廠方法中的具體工廠類就通常是一個單例。

5.工廠方法模式的相關模式

5.1 工廠方法模式和抽象工廠模式

這兩個模式可以組合使用,具體的放到抽象工廠模式中去講。

5.2 工廠方法模式和模板方法模式

這兩個模式外觀類似,都是有一個抽象類,然后由子類來提供一些實現,但是工廠方法模式的子類專注的是創建產品對象,而模板方法模式的子類專注的是為固定的算法骨架提供某些步驟的實現。

這兩個模式可以組合使用,通常在模板方法模式里面,使用工廠方法來創建模板方法需要的對象。

6.抽象工廠模式的相關模式

6.1 抽象工廠模式和工廠方法模式

這兩個模式既有區別,又有聯系,可以組合使用。

工廠方法模式一般是針對單獨的產品對象的創建,而抽象工廠模式注重產品簇對象的創建,這是它們的區別。

如果把抽象工廠創建的產品簇簡化,這個產品簇就只有一個產品,那么這個時候的抽象工廠跟工廠方法是差不多的,也就是抽象工廠可以退化成工廠方法,而工廠方法又可以退化成簡單工廠,這是它們的聯系。

在抽象工廠的實現中,還可以使用工廠方法來提供抽象工廠的具體實現,也就是說它們可以組合使用。

6.2 抽象工廠模式和單例模式

這兩個模式可以組合使用。

在抽象工廠模式里面,具體的工廠實現,在整個應用中,通常一個產品系列只需要一個實例就可以了,因此可以把具體的工廠實現成為單例。

7.生成器模式的相關模式

7.1 生成器模式和工廠方法模式

這兩個模式可以組合使用。

生成器模式的Builder實現中,通常需要選擇具體的部件實現,一個可行的方案就是實現成為工廠方法,通過工廠方法來獲取具體的部件對象,然后再進行部件的裝配。

7.2 生成器模式和抽象工廠模式

這兩個模式既相似又有區別,也可以組合使用

先說相似性,這個在課程里面已經詳細講述了,這里就不去重復了。

再說說區別:抽象工廠模式的主要目的是創建產品簇,這個產品簇里面的單個產品,就相當于是構成一個復雜對象的部件對象,抽象工廠對象創建完成過后就立即返回整個產品簇;而生成器模式的主要目的是按照構造算法,一步一步來構建一個復雜的產品對象,通常要等到整個構建過程結束過后,才會得到最終的產品對象。

事實上,這兩個模式是可以組合使用的,在生成器模式的Builder實現中,需要創建各個部件對象,而這些部件對象是有關聯的,通常是構成一個復雜對象的部件對象,也就是說,Builder實現中,需要獲取構成一個復雜對象的產品簇,那自然就可以使用抽象工廠模式來實現。這樣一來,由抽象工廠模式負責了部件對象的創建,Builder實現里面就主要負責產品對象整體的構建了。

7.3 生成器模式和模板方法模式

這也是兩個非常類似的模式。初看之下,不會覺得這兩個模式有什么關聯,但是仔細一思考,發現兩個模式在功能上很類似。

模板方法模式主要是用來定義算法的骨架,把算法中某些步驟延遲到子類中實現。再想想生成器模式,Director用來定義整體的構建算法,把算法中某些涉及到具體部件對象的創建和裝配的功能,委托給具體的Builder來實現。

雖然生成器不是延遲到子類,是委托給Builder,但那只是具體實現方式上的差別,從實質上看兩個模式很類似,都是定義一個固定的算法骨架,然后把算法中的某些具體步驟交給其它類來完成,都能實現整體算法步驟和某些具體步驟實現的分離。

當然兩個模式也有很大的區別,首先是模式的目的,生成器模式是用來構建復雜對象的,而模板方法是用來定義算法骨架,尤其是一些復雜的業務功能的處理算法的骨架;其次是模式的實現,生成器模式是采用委托的方法,而模板方法是采用的繼承的方式;另外從使用的復雜度上,生成器模式需要組合Director和Builder對象,然后才能開始構建,要等構建完后才能獲得最終的對象,而模板方法就沒有這么麻煩,直接使用子類對象即可。

7.4 生成器模式和組合模式

這兩個模式可以組合使用。

對于復雜的組合結構,可以使用生成器模式來一步一步構建。

8.原型模式的相關模式

8.1 原型模式和抽象工廠模式

功能上有些相似,都是用來獲取一個新的對象實例的。

不同之處在于,原型模式的著眼點是在如何創造出實例對象來,最后選擇的方案是通過克隆;而抽象工廠模式的著眼點則在于如何來創造產品簇,至于具體如何創建出產品簇中的每個對象實例,抽象工廠模式不是很關注。

正是因為它們的關注點不一樣,所以它們也可以配合使用,比如在抽象工廠模式里面,具體創建每一種產品的時候就可以使用該種產品的原型,也就是抽象工廠管產品簇,具體的每種產品怎么創建則可以選擇原型模式。

8.2 原型模式和生成器模式

這兩種模式可以配合使用。

生成器模式關注的是構建的過程,而在構建的過程中,很可能需要某個部件的實例,那么很自然地就可以應用上原型模式,通過原型模式來得到部件的實例。

9.中介者模式的相關模式

9.1 中介者模式和外觀模式

這兩個模式有相似的地方,也存在很大的不同。

外觀模式多用來封裝一個子系統內部的多個模塊,目的是向子系統外部提供簡單易用的接口,也就是說外觀模式封裝的是子系統外部和子系統內部模塊間的交互;而中介者模式是提供多個平等的同事對象之間交互關系的封裝,一般是用在內部實現上。

另外,外觀模式是實現單向的交互,是從子系統外部來調用子系統內部,不會反著來,而中介者模式實現的是內部多個模塊間多向的交互。

9.2 中介者模式和觀察者模式

這兩個模式可以組合使用。

中介者模式可以組合使用觀察者模式,來實現當同事對象發生改變的時候,通知中介對象,讓中介對象去進行與其它相關對象的交互。

10.代理模式的相關模式

10.1 代理模式和適配器模式

這兩個模式有一定的相似性,但也有差異。

這兩個模式有相似性,它們都為另一個對象提供間接性的訪問,而且都是從自身以外的一個接口向這個對象轉發請求。

但是從功能上,兩個模式是不一樣的。適配器模式主要用來解決接口之間不匹配的問題,它通常是為所適配的對象提供一個不同的接口;而代理模式會實現和目標對象相同的接口。

10.2 代理模式和裝飾模式

這兩個模式從實現上相似,但是功能上是不同的。

裝飾模式的實現和保護代理的實現上是類似的,都是在轉調其它對象的前后執行一定的功能。但是它們的目的和功能都是不同的。

裝飾模式的目的是為了讓你不生成子類就可以給對象添加職責,也就是為了動態的增加功能;而代理模式的主要目的是控制對對象的訪問。

11.觀察者模式的相關模式

11.1 觀察者模式和狀態模式

觀察者模式和狀態模式是有相似之處的。

觀察者模式是當目標狀態發生改變時,觸發并通知觀察者,讓觀察者去執行相應的操作。而狀態模式是根據不同的狀態,選擇不同的實現,這個實現類的主要功能就是針對狀態的相應的操作,它不像觀察者,觀察者本身還有很多其它的功能,接收通知并執行相應處理只是觀察者的部分功能。

當然觀察者模式和狀態模式是可以結合使用的。觀察者模式的重心在觸發聯動,但是到底決定哪些觀察者會被聯動,這時就可以采用狀態模式來實現了,也可以采用策略模式來進行選擇需要聯動的觀察者。

11.2 觀察者模式和中介者模式

觀察者模式和中介者模式是可以結合使用的。

前面的例子中目標都只是簡單的通知一下,然后讓各個觀察者自己去完成更新就結束了。如果觀察者和被觀察的目標之間的交互關系很復雜,比如:有一個界面,里面有三個下拉列表組件,分別是選擇國家、省份/州、具體的城市,很明顯這是一個三級聯動,當你選擇一個國家的時候,省份/州應該相應改變數據,省份/州一改變,具體的城市也需要改變。

這種情況下,很明顯需要相關的狀態都聯動準備好了,然后再一次性的通知觀察者,就是界面做更新處理,不會國家改變一下,省份和城市還沒有改,就通知界面更新。這種情況就可以使用中介者模式來封裝觀察者和目標的關系。

在使用Swing的小型應用里面,也可以使用中介者模式。比如:把一個界面所有的事件用一個對象來處理,把一個組件觸發事件過后,需要操作其它組件的動作都封裝到一起,這個對象就是典型的中介者。

12.命令模式的相關模式

12.1 命令模式和組合模式

這兩個模式可以組合使用。

在命令模式中,實現宏命令的功能,就可以使用組合模式來實現。前面的示例并沒有按照組合模式來做,那是為了保持示例的簡單,還有突出命令模式的實現,這點請注意。

12.2 命令模式和備忘錄模式

這兩個模式可以組合使用。

在命令模式中,實現可撤銷操作功能時,前面講了有兩種實現方式,其中有一種就是保存命令執行前的狀態,撤銷的時候就把狀態恢復回去。如果采用這種方式實現,就可以考慮使用備忘錄模式。

如果狀態存儲在命令對象里面,那么還可以使用原型模式,把命令對象當作原型來克隆一個新的對象,然后把克隆出來的對象通過備忘錄模式存放。

12.3 命令模式和模板方法模式

這兩個模式從某種意義上有相似的功能,命令模式可以作為模板方法的一種替代模式,也就是說命令模式可以模仿實現模板方法模式的功能。

如同前面講述的退化的命令模式可以實現Java的回調,而Invoker智能化后向服務進化,如果Invoker的方法就是一個算法骨架,其中有兩步在這個骨架里面沒有具體實現,需要外部來實現,這個時候就可以通過回調命令接口來實現。而類似的功能在模板方法里面,一個算法骨架,其中有兩步在這個骨架里面沒有具體實現,是先調用抽象方法,然后等待子類來實現。

可以看出雖然實現方式不一樣,但是可以實現相同的功能。

13.迭代器模式的相關模式

13.1 迭代器模式和組合模式

這兩個模式可以組合使用。

組合模式是一種遞歸的對象結構,在枚舉某個組合對象的子對象的時候,通常會使用迭代器模式。

13.2 迭代器模式和工廠方法模式

這兩個模式可以組合使用。

在聚合對象創建迭代器的時候,通常會采用工廠方法模式來實例化相應的迭代器對象。

14.組合模式的相關模式

14.1 組合模式和裝飾模式

這兩個模式可以組合使用。

裝飾模式在組裝多個裝飾器對象的時候,是一個裝飾器找下一個裝飾器,下一個再找下一個,如此遞歸下去。那么這種結構也可以使用組合模式來幫助構建,這樣一來,裝飾器對象就相當于組合模式的Composite對象了。

要讓兩個模式能很好的組合使用,通常會讓它們有一個公共的父類,因此裝飾器必須支持組合模式需要的一些功能,比如:增加、刪除子組件等等。

14.2 組合模式和享元模式

這兩個模式可以組合使用。

如果組合模式中出現大量相似的組件對象的話,可以考慮使用享元模式來幫助緩存組件對象,這可以減少對內存的需要。

使用享元模式也是有條件的,如果組件對象的可變化部分的狀態能夠從組件對象里面分離出去,而且組件對象本身不需要向父組件發送請求的話,就可以采用享元模式。

14.3 組合模式和迭代器模式

這兩個模式可以組合使用。

在組合模式中,通??梢允褂玫髂J絹肀闅v組合對象的子對象集合,而無需關心具體存放子對象的聚合結構。

14.4 組合模式和訪問者模式

這兩個模式可以組合使用。

訪問者模式能夠在不修改原有對象結構的情況下,給對象結構中的對象增添新的功能。將訪問者模式和組合模式合用,可以把原本分散在Composite和 Leaf類中的操作和行為都局部化。

如果在使用組合模式的時候,預計到今后可能會有增添其它功能的可能,那么可以采用訪問者模式,來預留好添加新功能的方式和通道,這樣以后在添加新功能的時候,就不需要再修改已有的對象結構和已經實現的功能了。

14.5 組合模式和職責鏈模式

這兩個模式可以組合使用。

職責鏈模式要解決的問題是:實現請求的發送者和接收者之間解耦。職責鏈模式的實現方式是把多個接收者組合起來,構成職責鏈,然后讓請求在這條鏈上傳遞,直到有接收者處理這個請求為止。

可以應用組合模式來構建這條鏈,相當于是子組件找父組件,父組件又找父組件,如此遞歸下去,構成一條處理請求的組件對象鏈。

14.6 組合模式和命令模式

這兩個模式可以組合使用。

命令模式中有一個宏命令的功能,通常這個宏命令就是使用組合模式來組裝出來的。

15.模板方法模式的相關模式

15.1 模板方法模式和工廠方法模式

這兩個模式可以配合使用。

模板方法模式可以通過工廠方法來獲取需要調用的對象。

15.2 模板方法模式和策略模式

這兩個模式的功能有些相似,但是是有區別的。

從表面上看,兩個模式都能實現算法的封裝,但是模板方法封裝的是算法的骨架,這個算法骨架是不變的,變化的是算法中某些步驟的具體實現;而策略模式是把某個步驟的具體實現算法封裝起來,所有封裝的算法對象是等價的,可以相互替換。

因此,可以在模板方法中使用策略模式,就是把那些變化的算法步驟通過使用策略模式來實現,但是具體選取哪個策略還是要由外部來確定,而整體的算法步驟,也就是算法骨架就由模板方法來定義了。

16.策略模式的相關模式

16.1 策略模式和狀態模式

這兩個模式從模式結構上看是一樣的,但是實現的功能是不一樣的。

狀態模式是根據狀態的變化來選擇相應的行為,不同的狀態對應不同的類,每個狀態對應的類實現了該狀態對應的功能,在實現功能的同時,還會維護狀態數據的變化。這些實現狀態對應的功能的類之間是不能相互替換的。策略模式是根據需要或者是客戶端的要求來選擇相應的實現類,各個實現類是平等的,是可以相互替換的。

另外策略模式可以讓客戶端來選擇需要使用的策略算法,而狀態模式一般是由上下文,或者是在狀態實現類里面來維護具體的狀態數據,通常不由客戶端來指定狀態。

16.2 策略模式和模板方法模式

這兩個模式可組合使用,如同前面示例的那樣。

模板方法重在封裝算法骨架,而策略模式重在分離并封裝算法實現。

16.3 策略模式和享元模式

這兩個模式可組合使用。

策略模式分離并封裝出一系列的策略算法對象,這些對象的功能通常都比較單一,很多時候就是為了實現某個算法的功能而存在,因此,針對這一系列的、多個細粒度的對象,可以應用享元模式來節省資源,但前提是這些算法對象要被頻繁的使用,如果偶爾用一次,就沒有必要做成享元了。

17.狀態模式的相關模式

17.1 狀態模式和觀察者模式

這兩個模式乍一看,功能是很相似的,但是又有區別,可以組合使用。

模式都是在狀態發生改變的時候觸發行為,只不過觀察者模式的行為是固定的,那就是通知所有的觀察者,而狀態模式是根據狀態來選擇不同的處理。

從表面來看兩個模式功能相似,觀察者中的被觀察對象就好比狀態模式中的上下文,觀察者模式中當被觀察對象的狀態發生改變的時候,觸發的通知所有觀察者的方法;就好比狀態模式中,根據狀態的變化,選擇對應的狀態處理。

但實際這兩個模式是不同的,觀察者模式的目的是在被觀察者的狀態發生改變的時候,觸發觀察者聯動,具體如何處理觀察者模式不管;而狀態模式的主要目的在于根據狀態來分離和選擇行為,當狀態發生改變的時候,動態改變行為。

這兩個模式是可以組合使用的,比如在觀察者模式的觀察者部分,當被觀察對象的狀態發生了改變,觸發通知了所有的觀察者過后,觀察者該怎么處理呢?這個時候就可以使用狀態模式,根據通知過來的狀態選擇相應的處理。

17.2 狀態模式和策略模式

這是兩個結構相同,功能各異的模式,具體的在策略模式里面講過了,這里不再贅述。

17.3 狀態模式和單例模式

這兩個模式可以組合使用,可以把狀態模式中的狀態處理類實現成單例。

17.4 狀態模式和享元模式

這兩個模式可以組合使用。

由于狀態模式把狀態對應的行為分散到多個狀態對象中,會造成很多細粒度的狀態對象,可以把這些狀態處理對象通過享元模式來共享,從而節省資源。

18.備忘錄模式的相關模式

18.1 備忘錄模式和命令模式

這兩個模式可以組合使用。

命令模式實現中,在實現命令的撤銷和重做的時候,可以使用備忘錄模式,在命令操作的時候記錄下操作前后的狀態,然后在命令撤銷和重做的時候,直接使用相應的備忘錄對象來恢復狀態就可以了。

在這種撤銷的執行順序和重做執行順序可控的情況下,備忘錄對象還可以采用增量式記錄的方式,可以減少緩存的數據量。

18.2 備忘錄模式和原型模式

這兩個模式可以組合使用。

在原發器對象創建備忘錄對象的時候,如果原發器對象中全部或者大部分的狀態都需要保存,一個簡潔的方式就是直接克隆一個原發器對象。也就是說,這個時候備忘錄對象里面存放的是一個原發器對象的實例,這個在前面已經示例過了,這里就不贅述了。

19.享元模式的相關模式

19.1 享元模式與單例模式

這兩個模式可以組合使用。

通常情況下,享元模式中的享元工廠可以實現成為單例。另外,享元工廠里面緩存的享元對象,都是單實例的,可以看成是單例模式的一種變形控制,在享元工廠里面來單例享元對象。

19.2 享元模式與組合模式

這兩個模式可以組合使用。

在享元模式里面,存在不需要共享的享元實現,這些不需要共享的享元通常是對共享的享元對象的組合對象,也就是說,享元模式通常會和組合模式組合使用,來實現更復雜的對象層次結構。

19.3 享元模式與狀態模式

這兩個模式可以組合使用。

可以使用享元模式來共享狀態模式中的狀態對象,通常在狀態模式中,會存在數量很大的、細粒度的狀態對象,而且它們基本上都是可以重復使用的,都是用來處理某一個固定的狀態的,它們需要的數據通常都是由上下文傳入,也就是變化部分都分離出去了,所以可以用享元模式來實現這些狀態對象。

19.4 享元模式與策略模式

這兩個模式可以組合使用。

可以使用享元模式來實現策略模式中的策略對象,跟狀態模式一樣,在策略模式中也存在大量細粒度的策略對象,它們需要的數據同樣是從上下文傳入的,所以可以使用享元模式來實現這些策略對象

20.解釋器模式的相關模式

20.1 解釋器模式和組合模式

這兩個模式可以組合使用。

通常解釋器模式都會使用組合模式來實現,這樣能夠方便的構建抽象語法樹。一般非終結符解釋器就相當于組合模式中的組合對象,終結符解釋器就相當于葉子對象。

20.2 解釋器模式和迭代器模式

這兩個模式可以組合使用。

由于解釋器模式通常使用組合模式來實現,因此在遍歷整個對象結構的時候,自然可以使用迭代器模式。

20.3 解釋器模式和享元模式

這兩個模式可以組合使用。

在使用解釋器模式的時候,可能會造成多個細粒度對象,比如會有各種各樣的終結符解釋器,而這些終結符解釋器對不同的表達式來說是一樣的,是可以共用的,因此可以引入享元模式來共享這些對象。

20.4 解釋器模式和訪問者模式

這兩個模式可以組合使用。

在解釋器模式中,語法規則和解釋器對象是有對應關系的。語法規則的變動意味著功能的變化,自然會導致使用不同的解釋器對象;而且一個語法規則可以被不同的解釋器解釋執行。

因此在構建抽象語法樹的時候,如果每個節點所對應的解釋器對象是固定的,這就意味著這個節點對應的功能是固定的,那么就不得不根據需要來構建不同的抽象語法樹。

為了讓構建的抽象語法樹較為通用,那就要求解釋器的功能不要那么固定,要能很方便的改變解釋器的功能,這個時候問題就變成了,如何能夠很方便的更改樹形結構中節點對象的功能了,訪問者模式可以很好的實現這個功能。

21.裝飾模式的相關模式

21.1 裝飾模式與適配器模式

這是兩個沒有什么關聯的模式,放到一起來說,是因為它們有一個共同的別名:Wrapper。

這兩個模式功能上是不一樣的,適配器模式是用來改變接口的,而裝飾模式是用來改變對象功能的。

21.2 裝飾模式與組合模式

這兩個模式有相似之處,都涉及到對象的遞歸調用,從某個角度來說,可以把裝飾看成是只有一個組件的組合。

但是它們的目的完全不一樣,裝飾模式是要動態的給對象增加功能;而組合模式是想要管理組合對象和葉子對象,為它們提供一個一致的操作接口給客戶端,方便客戶端的使用。

21.3 裝飾模式與策略模式

這兩個模式可以組合使用。

策略模式也可以實現動態的改變對象的功能,但是策略模式只是一層選擇,也就是根據策略選擇一下具體的實現類而已。而裝飾模式不是一層,而是遞歸調用,無數層都可以,只要組合好裝飾器的對象組合,那就可以依次調用下去,所以裝飾模式會更靈活。

而且策略模式改變的是原始對象的功能,不像裝飾模式,后面一個裝飾器,改變的是經過前一個裝飾器裝飾過后的對象,也就是策略模式改變的是對象的內核,而裝飾模式改變的是對象的外殼。

這兩個模式可以組合使用,可以在一個具體的裝飾器里面使用策略模式,來選擇更具體的實現方式。比如前面計算獎金的另外一個問題就是參與計算的基數不同,獎金的計算方式也是不同的。舉例來說:假設張三和李四參與同一個獎金的計算,張三的銷售總額是2萬元,而李四的銷售額是8萬元,它們的計算公式是不一樣的,假設獎金的計算規則是,銷售額在5萬以下,統一3%,而5萬以上,5萬內是4%,超過部分是6%。

參與同一個獎金的計算,這就意味著可以使用同一個裝飾器,但是在裝飾器的內部,不同條件下計算公式不一樣,那么怎么選擇具體的實現策略呢?自然使用策略模式就好了,也就是裝飾模式和策略模式組合來使用。

21.4 裝飾模式與模板方法模式

這是兩個功能上有相似點的模式。

模板方法模式主要應用在算法骨架固定的情況,那么要是算法步驟不固定呢,也就是一個相對動態的算法步驟,就可以使用裝飾模式了,因為在使用裝飾模式的時候,進行裝飾器的組裝,其實也相當于是一個調用算法步驟的組裝,相當于是一個動態的算法骨架。

既然裝飾模式可以實現動態的算法步驟的組裝和調用,那么把這些算法步驟固定下來,那就是模板方法模式實現的功能了,因此裝飾模式可以模擬實現模板方法模式的功能。

但是請注意,僅僅只是可以模擬功能而已,兩個模式的設計目的、原本的功能、本質思想等都是不一樣的。

22.職責鏈模式的相關模式

22.1 職責鏈模式和組合模式

這兩個模式可以組合使用。

可以把職責對象通過組合模式來組合,這樣可以通過組合對象自動遞歸的向上調用,由父組件作為子組件的后繼,從而形成鏈。這也就是前面提到過的使用外部已有的鏈接,這種情況在客戶端使用的時候,就不用再構造鏈了,雖然不構造鏈,但是需要構造組合對象樹,是一樣的。

22.2 職責鏈模式和策略模式

這兩個模式可以組合使用。

這兩個模式有相似之處,如果把職責鏈簡化到直接就能選擇到相應的處理對象,那就跟策略模式的選擇差不多,因此可以用職責鏈來模擬策略模式的功能。只是如果把職責鏈簡化到這個地步,也就不存在鏈了,也就稱不上是職責鏈了。

兩個模式可以組合使用,可以在職責鏈模式的某個職責的實現的時候,使用策略模式來選擇具體的實現,同樣也可以在策略模式的某個策略實現里面,使用職責鏈模式來實現功能處理。

同理職責鏈模式也可以和狀態模式組合使用。

22.3 職責鏈模式和裝飾模式

這兩個模式相似,從某個角度講,可以相互模擬實現對方的功能。

裝飾模式能夠動態的給被裝飾對象添加功能,要求裝飾器對象和被裝飾的對象實現相同的接口。而職責鏈模式可以實現動態的職責組合,標準的功能是有一個對象處理就結束,但是如果處理完本職責不急于結束,而是繼續向下傳遞請求,那么功能就和裝飾模式的功能差不多了,每個職責對象就類似于裝飾器,可以實現某種功能。

而且兩個模式的本質也類似,都需要在運行期間動態組合,裝飾模式是動態組合裝飾器,而職責鏈是動態組合處理請求的職責對象的鏈。

但是從標準的設計模式上來講,這兩個模式還是有較大區別的,這點要注意。首先是目的不同,裝飾模式是要實現透明的為對象添加功能,而職責鏈模式是要實現發送者和接收者解耦;另外一個,裝飾模式是無限遞歸調用的,可以有任意多個對象來裝飾功能,但是職責鏈模式是有一個處理就結束。

23.橋接模式的相關模式

23.1 橋接模式和策略模式

這兩個模式有很大的相似之處。

如果把橋接模式的抽象部分簡化來看,如果暫時不去擴展Abstraction,也就是去掉 RefinedAbstraction。會發現,這個時候它們的結構都類似如圖所示:


通過上面的結構圖,可以體會到橋接模式和策略模式是如此相似??梢园巡呗阅J降腃ontext視做是使用接口的對象,而Strategy就是某個接口了,具體的策略實現那就相當于接口的具體實現。這樣看來的話,某些情況下,可以使用橋接模式來模擬實現策略模式的功能。

這兩個模式雖然相似,也還是有區別的。最主要的是模式的目的不一樣,策略模式的目的是封裝一系列的算法,使得這些算法可以相互替換;而橋接模式的目的是分離抽象和實現部分,使得它們可以獨立的變化。

23.2 橋接模式和狀態模式

由于從模式結構上看,狀態模式和策略模式是一樣的,這兩個模式的關系也基本上類似于橋接模式和策略模式的關系。

只不過狀態模式的目的是封裝狀態對應的行為,并在內部狀態改變的時候改變對象的行為。

23.3 橋接模式和抽象工廠模式

這兩個模式可以組合使用。

橋接模式中,抽象部分需要獲取相應的實現部分的接口對象,那么誰來創建實現部分的具體實現對象呢?這就是抽象工廠模式派上用場的地方。也就是使用抽象工廠模式來創建和配置一個特定的具體實現的對象。

事實上,抽象工廠主要是用來創建一系列對象的,如果創建的對象很少,或者是很簡單,還可以采用簡單工廠,可以達到一樣的效果,但是會比抽象工廠來得簡單。

23.4 橋接模式和模板方法模式

這兩個模式有相似之處。

雖然標準的模板方法模式是采用繼承來實現的,但是模板方法也可以通過回調接口的方式來實現,如果把接口的實現獨立出去,那就類似于模板方法通過接口去調用具體的實現方法了。這樣的結構就和簡化的橋接模式類似了。

可以使用橋接模式來模擬實現模板方法模式的功能。如果在實現Abstraction對象的時候,在里面定義方法,方法里面就是某個固定的算法骨架,也就是說這個方法就相當于模板方法。在模板方法模式里,是把不能確定實現的步驟延遲到子類去實現;現在在橋接模式里面,把不能確定實現的步驟委托給具體實現部分去完成,通過回調實現部分的接口,來完成算法骨架中的某些步驟。這樣一來,就可以實現使用橋接模式來模擬實現模板方法模式的功能了。

使用橋接模式來模擬實現模板方法模式的功能,還有個潛在的好處,就是模板方法也可以很方便的擴展和變化了。在標準的模板方法里面,一個問題就是當模板發生變化的時候,所有的子類都要變化,非常不方便。而使用橋接模式來實現類似的功能,就沒有這個問題了。

另外,這里只是說從實現具體的業務功能上,橋接模式可以模擬實現出模板方法模式能實現的功能,并不是說橋接模式和模板方法模式就變成一樣的,或者是橋接模式就可以替換掉模板方法模式了。要注意它們本身的功能、目的、本質思想都是不一樣的。

23.5 橋接模式和適配器模式

這兩個模式可以組合使用。

這兩個模式功能是完全不一樣的,適配器模式的功能主要是用來幫助無關的類協同工作,重點在解決原本由于接口不兼容而不能一起工作的那些類,使得它們可以一起工作。而橋接模式則重點在分離抽象和實現部分。

所以在使用上,通常在系統設計完成過后,才會考慮使用適配器模式;而橋接模式,是在系統開始的時候就要考慮使用。

雖然功能上不一樣,這兩個模式還是可以組合使用的,比如:已有實現部分的接口,但是有些不太適應現在新的功能對接口的需要,完全拋棄吧,有些功能還用得上,該怎么辦呢?那就使用適配器來進行適配,使得舊的接口能夠適應新的功能的需要。

24.訪問者模式的相關模式

24.1 訪問者模式和組合模式

這兩個模式可以組合使用。

如同前面示例的那樣,通過訪問者模式給組合對象預留下擴展功能的接口,使得給組合模式的對象結構添加功能非常容易。

24.2 訪問者模式和裝飾模式

這兩個模式從表面看功能有些相似,都能夠實現在不修改原對象結構的情況下修改原對象的功能。但是裝飾模式更多的是實現對已有功能加強、或者修改、或者完全全新實現;而訪問者模式更多的是實現給對象結構添加新的功能。

24.3 訪問者模式和解釋器模式

這兩個模式可以組合使用。

解釋器模式在構建抽象語法樹的時候,是使用組合模式來構建的,也就是說解釋器模式解釋并執行的抽象語法樹是一個組合對象結構,這個組合對象結構是很少變動的,但是可能經常需要為解釋器增加新的功能,實現對同一對象結構的不同解釋和執行的功能,這正好是訪問者模式的優勢所在,因此這在使用解釋器模式的時候通常會組合訪問者模式來使用。

后續應該做的事

不是結束而是新的開始。并不是說你就不用再學習設計模式了,恰恰相反,要想在設計上更進一步的話,困難才剛剛開始。從中級的水平向上發展,更多的是需要思考和領悟,其難度比從入門到中級要大得多。因此對你而言,學到這里并不是學習的結束,而是新的開始。

你該怎么做

  • 1)多看
    多搜尋一些應用設計模式的實際項目、工程或是框架,參考別人的成功應用,再結合自己的經驗來思考和使用。當然項目不應該太大,太大了很難完全看懂;也不能太小,太小了,沒有太大實用價值,尤其是無法參考多個模式綜合應用的情況,幫助就不大了。
  • 2)多練
    多尋找機會,把這些設計模式在實際應用中使用,只有親自動手去試驗和使用,才能真正掌握和領會設計模式的精髓。
  • 3)多總結:認真分析每次對設計模式的使用是否得當,有什么經驗和教訓,是否有變形使用的情況,在不斷總結中進步。
  • 4)反復參閱《研磨設計模式》一書:理論聯系實際,通過實際應用反過來加深對理論的理解,以達到融會貫通這些設計模式的知識。因此,你需要反復參閱《研磨設計模式》一書,看看書上的知識,然后實踐,然后再回頭看書上的知識,你會有不一樣的體會和領悟。
  • 5)多思考:多從設計上去思考這些設計模式,考慮它的設計意圖、設計思想、解決問題的方式、實現的原理、模式的本質、以及如何變形使用等等。只要你堅持去按照上面說的做,假以時日,必有所成。

參考

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372

推薦閱讀更多精彩內容

  • 設計模式概述 在學習面向對象七大設計原則時需要注意以下幾點:a) 高內聚、低耦合和單一職能的“沖突”實際上,這兩者...
    彥幀閱讀 3,763評論 0 14
  • 設計模式匯總 一、基礎知識 1. 設計模式概述 定義:設計模式(Design Pattern)是一套被反復使用、多...
    MinoyJet閱讀 3,957評論 1 15
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,781評論 18 139
  • 總監找我問說 你是不是快要走了 我說是的 問什么原因 我答快要結婚了 說出去這句話就覺得很不舒服 總感...
    恭雖豈止閱讀 247評論 0 0
  • 每個人都有夢想成真的機會,關鍵是你能否把握來到身邊的機會!
    f15d57595d1c閱讀 341評論 0 0