?
l ? 創建模式
1. ?????? 工廠模式
簡單工廠:又稱靜態工廠方法模式,它可以根據傳進來的參數來選擇創建哪些對象。這樣方便,但有個缺點,因為工廠模式本來就是為了將對象的使用和創建脫藕,而如果使用簡單工廠模式的話,那么客戶端就需要知道要創建的對象的類型。
工廠方法:又稱多態性工廠模式。工廠模式的核心是一個抽象工廠類,而簡單工廠模式把核心放在一個具體類上。工廠方法模式可以允許很多具體工廠從抽象工廠類中將創建行為繼承下來,從而可以成為多個簡單工廠模式的統合,進而推廣了簡單工廠類。而且,當需要創建新的對象時,簡單工廠需要直接改源代碼,而工廠方法模式只需要再創建一個工廠類繼續抽象工廠類就可以了。同時,如果要創建的對象具體很深的層次的話,對應的工廠也可以和對象建立同樣的等級,這樣使用起來更方便,而簡單工廠就亂套的多。
抽象工廠:又稱工具箱模式。抽象工廠不是為了創建單一的對象而存在的,它是為了創建一個產品族群。
2. ?????? 單例模式
單例模式分為兩種,懶漢模式和餓漢模式。
餓漢模式:
Private static final EagerSingleton m_instance = new EagerSingleton();
當這個類被加載時,靜態變量 m_instance 就會被初始化,此時類的私有構造子會被調用,這時候,單例類的惟一實例就被創建出來了。
懶漢模式:
synchronized public static LazySingleton getInstance(){
???????? If(m_instance == null){
?????????????????? m_instance= new LazySingleton();
}else
return m_instance;
}
加 synchronized 是為了實現同步化。
餓漢模式在資源利用上不如懶漢模式,但因為沒有它天然就是線程安全的,不需要 synchronized ,所以它在速度和反應時間上比餓漢好。
餓漢模式在 java 可以實現,但在 c++ 中很難,因為靜態初始化在 c++ 中沒有固定的順序,因而靜態的 m_instance 變量的初始化與類的加載順序沒有保證,可能會出問題。
單例模式分關有狀態的和沒狀態的兩種,當有狀態時,它可以作為一個狀態庫使用,用來給系統提供一些信息。當用到分布式,比如 ejb 中時,需要跨 jvm 的運行,如果要用到單例類,那么會在每個 jvm 中都創建相應的實例,這時,就應該使用沒有狀態的單例。
3. ?????? 建造模式( builder )
建造模式和抽象工廠模式有些相似,但它們的關注的方面不同。抽象工廠是創建一個產品族,所以它的創建一般只有一個方法,然后就返回創建好的產品,可以再用來加工,也可以直接使用。而建造模式,一般都有好幾個創建方法,用來逐漸創建 Product ,它的所有創建方法必須都使用才能創建一個完整的產品,然后再用 retrieveResult() 方法來返回所創建的產品。
4. ?????? 原始模型( Prototype )模式
原始模型模式是給出一個原型對象來指明所要他要創建的對象類型,然后用復制這個原型對象的方法創建出更多同類型的對象。換句話說,就是克隆。
Java 語言的構件模型直接支持原始模型模式。所有的 javabean 都繼承自 java.lang.Object ,而 Object 類提供了一個 clone() 方法,可以將 JavaBean 對象復制一份。但是,這個 javabean 必須實現標識接口 Cloneable ,表明這個 javabean 支持復制。如果不實現就調用 clone() 方法,則拋出 CloneNotSupportedException 異常。( clone 方法的返回類型是 Object ,所以在子類重寫該方法的時候要注意一下)
通常來說,克隆要滿足幾個條件
? ? ? ? ? ? ? ? ? ? ? ? ? i. ????????????? 對任何的對象 x ,都有: x.clone()!=x 。換言之,克隆對象與原對象不是同一個對象。
? ? ? ? ? ? ? ? ? ? ? ? ii. ????????????? 對任何的對象 x ,都有: x.clone().getClass == x.getClass() ,換言之克隆對象與原始對象的類型一樣。(即使重寫 clone ()返回類型是 Object ,但它的 getClass 依然為創建時的 class )
? ? ? ? ? ? ? ? ? ? ?? iii. ????????????? 如果對象 x 的 equals() 方法定義恰當的話,那么 x.clone().equals(x) 應當成立(不要求必須,但最好)。
復制又分為兩種,淺復制和深復制。淺復制只復制對象的所有變量,而引用的對象還是原來的對象,也就是說,當淺復制時,兩個不同的對象,它們引用了同一個對象(如果有的話)。
深復制是指連引用的對象也一并復制。但引用的對象還可能引用別的對象,所以深復制要深入多少層,是一個不易確定的問題。而且可能出現循環引用,要小心使用。
可以利用串行化( Serilization )過程來深復制,把對象寫進流里再讀出來,那就是個完全的深復制,但效率太低。
l ? 結構模式
結構模式( Structural Pattern )描述如何將類或者對象結合在一起形成更大的結構。結構模式描述兩種不同的東西:類與類的實例。根據這一不同,結構模式可以分為類的結構模式和對象的結構模式。
5. ?????? 適配器模式( Adapter )
適配器模式是把一個類的接口變換成客戶端所期待的另一種接口,從而使原本因接口不匹配而無法在一起工作的兩個類能夠在一起工作。
它分為兩種,類的適配器和對象的適配器
類的適配器,要適配的類含有目標接口的( SpecificRequest ())方法,所以子類 Adapter 不用重寫,只要把源( Adaptee )沒有的方法, Request 實現就可以了。
對象的適配器
適配器的特例:缺省適配模式( Default Adapter ),為一個接口提供缺省實現,這樣子類型可以從這個缺省實現進行擴展,而不必從原有接口進行擴展。作為適配器模式的一個特例,缺省適配模式在 java 語言中有著特殊的應用。
這樣天星類就是一個抽象的適配器類,魯智深現在不需要實現吃齋等方法,因為他不做,而是只要實現他做的方法就行了。
6. ????? 合成模式( Composite )
合成模式又叫做部分 - 整體模式,將對象組織到樹結構中,可以用來描述整體與部分的關系。合成模式可以使客戶端將單純元素與復合元素同等看待。
合成模式分為兩種,透明方式和安全方式。上圖就是透明方式,在 Component 里聲明所有的用來管理子類對象的方法,包括 add ()、 remove ()、 getChild ()方法。這樣做的好處是所有的構件類都有相同的接口。在客戶端看來,樹葉類對象與合成類對象的區別起碼在接口層次上消失了,客戶端可以同等地對待所有的對象。
這個選擇缺點是不夠安全,因為樹葉類對象和合成類對象本質上是有區別的。樹葉類對象不可能有下一個層次的對象,因此 add 等方法是沒有意義的,但在編譯時期不會出錯,而只會在運行時代奢會出錯。
安全方式,是在 Composite 里聲明所有的用來管理子類對象的方法,而 Component 里的 add 、 remove 、 getChild 方法移到 Composite 里,這是安全的,因為樹葉類型的對象根本沒有管理子類對象的方法,因此,如果客戶端對樹葉類對象使用這些方法時,程序會在編譯時期出錯。這些的缺點是不夠透明,因為樹葉類和合成類將具有不同的接口。
7. ?????? 裝飾模式( Decorator )
裝飾模式以對客戶端透明的方式擴展對象的功能,是繼承關系的一個替代方案。
裝飾模式的上層可以看作是個合成模式。
裝飾模式與繼承模式都能擴展對象的功能,但裝飾模式更靈活,它可以選擇給對象裝飾成不同的樣式,比如用 ConcreteDectorator1 或 ConcreteDectorator2 裝飾,這些都可以由系統動態決定,而繼承是靜態的,編譯時就決定了。
由于要面對抽象編程,所以透明的裝飾模式應該這樣用:
Component c = new ConcreteComonent();
Comoponent c1 = new ConcreteDectorator1(c);
Comoponent c2 = new ConcreteDectorator2(c1);
而下面的是不對的
ConcreteComonent c = new ConcreteDectorator();
裝飾模式對客戶端是完全透明的。它們一系列的方法都有最初的 Component 接口所定義。但是,純粹的裝飾模式很難找到。裝飾模式的用意是在不改變接口的前提下,增強所考慮的類的性能。在增強性能的時候,往往需要那門新的公開的方法。比如在 io 系統中, BufferedInputStream 是負責裝飾 InputStream 的,但它為了增強處理緩存的功能,提供了額外的方法,比如 ensureopen() 、 fill() 等。所以它是一個半透明的裝飾類,如果想使用這些方法,就要將 inputStream 轉化為 BufferedInputStream 。
8. ?????? 代理模式( Proxy )
代理模式給某一個對象提供一個代理對象,并由代理對象控制對原對象的引用。通常情況下,如果被代理的對象需要很長的加載時間,比如數據庫或遠程方面的話, Proxy 可以在被代理對象真正創建的時候再去實例化它。
Proxy 類中有段代碼:
Private RelalSubject realSubject;
?
Public void request(){
// 方法調用前執行
preRequest();
if(realSubject == null){
?????????????????? realSubject = new RealSubject();
???????? }
???????? realSubject.request();
???????? // 方法調用完后執行
???????? afterRequest();
}
這樣不僅能延遲加載,也能面向切面編程,實際上, aop 就是用了這個原理。
代理模式看起來和適配器模式很相似,但它們有質的區別。適配器模式是為了改變所考慮的對象的接口,而代理模式并不能改變所代理的對象的接口。雖然 RealSubject 看起來即使不繼承 Subject 也沒有關系,這樣可以轉化為委托模式,但系統可以選擇使用代理,當然也可以選擇不使用代理,直接使用 RealSubject ,這時,就需要它去實現 Subject 接口了。所以 RealSubject 和 Proxy 的公用方法必須一致。
9. ?????? 享元模式 (FlyWeight Pattern)
?
術語粗粒度和細粒度用來形容由組件的公共接口所暴露的細節層次的。細粒度組件通過其公共接口暴露了有關組件如何工作的大量細節,所以它的重用性比較好,但不靈活。提供公共接口但并不暴露其操作細節的組件則稱為粗粒度,它重用性差,但更靈活。
細粒度的查詢任務的接口
interface TaskService{
? public List getTaskById(int id);
? public List getTaskByName(String name);
? public List getTaskByAge(int age);
}
那么粗粒度的接口該是什么樣的呢?
interface TaskService{
? public List getTask(Person person);
}
?
享元模式以共享的方式高效地支持大量的細粒度對象。能做到共享的關鍵是區分內蘊狀態和外蘊狀態。
一個內蘊狀態是存儲在享元對象內部的,并且是不會隨環境改變而有所不同的。因此,一個享元可以具有內蘊狀態并可以共享。
一個外蘊狀態是隨環境改變而改變的、不可以共享的狀態。享元對象的外蘊狀態必須由客戶端保存,并在享元對象被創建之后,在需要使用的時候再傳入到享元對象內部。外蘊狀態不可能影響享元對象的內蘊狀態。換句話說,它們是相互獨立的。
在 java 語言中, String 類型就是使用了享元模式。 String 對象是不變對象,一旦創建出來就不能改變。如果需要改變一個字符串的值,就只好創建一個新的 String 對象。在 jvm 內部, String 對象都是共享的,如果一個系統中有兩個 String 對象所包含的字符串相同的話, jvm 實際上只創建一個 String 對象提供給兩個引用。從而實現 String 對象的共享。 String 的 intern() 方法給出這個字符串的共享池中的惟一實例。
客戶端不能將具體享元對象實例化,而是必須通過工廠對象 FlyweightFactory 使用 getFlyweight(key) 來得到享元對象。并有一個 map 來存放這些對象,即如果已經創建過,就直接得到,如果沒有創建過,那就新建。 Flyweight 提供了方法 Operation() ,這是可以通過參量方式傳入一個外蘊狀態。
class ConcreteFlyweight implements Flyweight{
???????? // 內蘊狀態
???????? private Character intrinsicState = null;
???????? // 構造子,內蘊狀態作為參量傳入, FlyweightFactory 工廠創建
???????? Public ConcreteFlyweight(Charater state){
?????????????????? This.intrinsicState = state;
???????? }
???????? // 外蘊狀態作為參量傳入方法中,改變方法的行為,但是并不改變對象的內蘊狀態
???????? public void operation(String state){
?????????????????? System.out.println(“ 內蘊狀態 =”+? state+” 外蘊狀態 =”+state);
???????? }
}
這樣,通過調用 operation 方法,可以在不改變內蘊狀態 intrinsicState 的情況下,任意改變外蘊狀態。
享元模式優點在于能大同謀地降低內存中對象的數量。但是它使得系統更加復雜,為了使對象可以共享,需要將一些狀態外部化,這使得程序的邏輯復雜化。
10. ?????? 門面模式( Facade )
迪米特法則說:“只與你直接的朋友們通信”。迪米特法要求每一個對象與其他對象的相互作用均是第三種的,而不是長和的。只要可能,朋友的數目越少越好。換言之,一個對象只應當知道它的直接合作者的接口。
門面模式創建出一個門面對象,將客戶端所涉及的屬于一個子系統的協作伙伴的數目減到最少,使得客戶端與子系統內部的對象的相互作用被門面對象所取代。顯然,門面模式就是實現代碼重構以便達到迪米特法則要求的一個強有國的武器。
11. ?????? 橋梁模式( Bridge )
橋梁模式的用意是將抽象化與實現化脫耦,使得二者可以獨立地變化。
找到系統的可變因素,將之封裝起來,通常就叫做對變化的封裝。對變化的封裝實際上是達到“開 - 閉”原則的途徑,與組合 / 聚合復用原則是相輔相成的。
一般來說,一個繼承結構中的第一層是抽象角色,封裝了抽象的商業邏輯,這是系統中不變的部分。第二層是實現角色,封裝了設計中會變化的因素。這個實現請允許實現化角色有多態性變化。
當實現化需要改變時,就換個實現化;但當抽象化模塊需要改變時,比如公共算法的改變,再添加一些其它功能,這樣就得改整個系統。所以要將抽象化與實現化脫耦。
Jdbc 驅動器就是用了橋接模式
對象形式的的適配器模式可能看上去很像橋梁模式。然而適配器模式的目的是要改變已有的接口,讓它們可以相容,以使沒有關系的兩個類能在一起工作。而橋梁模式是分享抽象化和實現化,使得兩者的接口可以不同。因此兩個模式是相反方向努力。
行為模式
行為模式( Behavioral Pattern )是對在不同的對象之間劃分責任和算法的抽象化。行為模式不僅僅是關于類和對象的,而且是關于它們之間的相互作用的。
12. ?????? 不變模式( Immutable )
一個對象的狀態在對象被創建之后就不再變化,這就是所謂的不變模式。
不變模式可增強對象的強壯性。不變模式允許多個對象共享某一對象,降低了對該對象發訪問時的同步化開銷。如果需要修改一個不變對象的狀態,那么就需要建立一個新的同類的對象,并在創建時將這個新的狀態存儲在新對象里。
不變模式分為兩種:弱不變,所考慮的對象沒有任何方法會修改對象的狀態;這樣一來,當對象的構造子將對象的狀態初始化之后,對象的狀態便不再改變。所有屬性都應當是私有的,不要聲明任何的公開的屬性,以防客戶端對象直接修改任何的內部狀態。這個對象所引用到的其它對象如果是可變對象的話,必須高潮限制外界改變這些引用的可變對象。最好將這可變對象復制一份,不要使用原來的拷貝。
但它的子對象可以是可變對象;子對象可能可以修改父對象的狀態,從而可能會允許外界修改父對象的狀態;
強不變:一個類的實例狀態不會改變;同時它的子類的實例也具有不可變化的狀態。這樣的類符合強不變模式。必須滿足下面條件之一。
<!--[if !supportLists]--> 1. ????????????? <!--[endif]--> 所考慮的類所有的方法都應當是 final ;這樣這個類的子類不能夠轉換掉此類的方法;
<!--[if !supportLists]--> 2. ????????????? <!--[endif]--> 這個類本身就是 final 的,那么這個類就不可能會有子類,從而也就不可能有被子類修改的問題。
不變和之讀是有區別的:比如一個人的出生年月是不變的,而一個人的年齡便是只讀的,它會變化,但不能人為的改變。
不變模式的優點: 1. 因為不能修改一個不變對象的狀態,所以可以避免由此引起的不必要的程序錯誤:換言之,一個不變對象要比可變對象的對象更加容易維護。 2. 因為沒有任何一個線程能夠修改不變對象的內部狀態,一個不變對象自動就是線程安全的,這樣就可以省掉處理同步化的開銷。
13. ?????? 策略模式( Strategy )
策略模式是針對一組算法,將每個算法封裝到具有共同接口的獨立的類中,從而使得它們可以相互替換。策略模式使得算法可以在不影響到客戶的情況下發生變化。
策略模式是對算法的包裝,是把使用算法的責任和算法本身分割開,委派給不同的對象管理。策略模式通常把一個系列的算法包裝到一系列的策略類里面,作為一個抽象策略的子類。用一句話說,就是:“準備一組算法,并將每一個算法封裝起來,使得它們可以互換”。
14. ?????? 模板方法模式( Template Method )
準備一個抽象類,將部分邏輯以具體方法以及具體構造子的形式實現,然后聲明一些抽象方法來迫使子類實現剩余的邏輯。不同的子類可以以不同的方式實現這些抽象方法,從而對剩余的邏輯有不同的實現。
15. ?????? 觀察者模式
觀察者模式分為兩種,推模型和拉模型。
?
拉模型
推模型
通常情況下用拉模式更何情何理,既然是觀察對象,那么觀察者 observer 應該自己可以去把想要的數據弄過來。但是,拉模式中,觀察都需要有個觀察對象的引用。而這在推模型中是不需要的。
但推模型有個好處,就是當觀察對象有一堆數據,但只有很少的幾個做了變化時,拉模型的 observer 是不知道哪些起了變化的,它只能遍歷 subject 的所有屬性;而推模型就可以把起變化的數據推給觀察者,同時能有個 hint 來做提示,當然,它可以是個參數、枚舉、字符串等,它的值都可以推給觀察者。
16. ?????? 迭代子模式( Iterator )
迭代子模式又叫游標模式,可以順序地訪問一個聚集中的元素而不必暴露聚集的內部表象。
聚集對象必須提供適當的方法,允許客戶端能夠按照一個線性順序遍歷所有元素對象,把元素對象提取出來或者刪掉掉等。那么就會出現兩種情況: 1. 迭代邏輯沒有改變,但是需要將一種聚集換成另一種聚集,如果它們有不同的遍歷接口,那就要改客戶端代碼。 2. 聚集不改變,但迭代方式要改變,比如以前只要讀取元素和刪除元素,現在又加上添加元素,這時就只好修改聚集對象,修改已有的遍歷方法。所以使用聚集時,就需要迭代子。
如果一個聚集的接口提供了可以用來修改聚集元素的方法,這個接口就是寬接口;如果一個聚集的接口沒有提供修改聚集元素的方法,這樣的接口就是窄接口。
上圖中, Aggregate 對 client 就是窄接口,顯然不想讓客戶端能夠直接改變聚集的內容;而 ConcreteAggregate 對 ConcreateIterator 就是寬接口,具體迭代子必須能夠控制聚集的內容。
上圖所示的是白箱聚集與外稟迭代子。
外稟指具體迭代子類是在外面,而內稟則是具體迭代子類是具體聚集的內部類,這樣能夠訪問具體聚集的私有成員和方法。
白箱聚集向外界提供訪問自己內部元素的接口,從而使外稟迭代子可以通過聚集的遍歷方法實現迭代功能,如上圖,但這樣是不安全的,如果 client 沒有使用迭代子,直接使用白箱聚集的操作接口,就可能出現問題。
黑箱聚集不向外部提供遍歷自己元素對象的接口,因此,這些元素對象只可以被內部成員訪問。這時就用到內稟迭代子了。
由于迭代子要存儲當前遍歷的游標(當前元素位置),所以白箱聚集使用外稟迭代子時,可以是不變對象,前提是它的聚集元素是不會改變的。但黑箱由于提供的內稟迭代子必須存儲動態的游標,所以它不可能是不變對象。
AbstractList 是白箱聚集,它向外部提供了自己的遍歷方法,所以我們可以自定義自己的外稟迭代子,但它也使用了內稟迭代子,即內部類 Itr ,做為默認的迭代實現。
17. ?????? 責任鏈模式( Chain of Responsibility )
在責任鏈模式里,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某個對象決定處理些請求。發出這個請求的客戶端并不知道鏈上的哪一個對象最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織鏈和分配責任。
具體處理者( ConcreteHandler )接到請求后,可以選擇將請求處理掉,或者將請求傳給下家。由于具體處理者持有對下家的引用,因此,如果需要,具體處理者可以訪問下家。
責任鏈模式分為兩種。一個純的責任鏈模式要求一個具體的處理者對象只能在兩個行為中選擇一個:一個是承擔責任,二是把責任推給下家。不允許出現某一個具體處理者對象在承擔了一部分責任后又把責任向下傳的情況。在一個純的責任鏈模式里面,一個請求必須被某一個處理者對象所接收;在一個不純的責任鏈模式里,一個請求可以最終不被任何接收端對象所接收。
鏈結構的由來:責任鏈模式并不創建出責任鏈,而是由系統的其它部分比如客戶端來創建出來。客戶端負責將每個責任對象創建出來,并手動指定責任對象的下家。
18. ?????? 命令模式
命令模式把一個請求或者操作封裝到一個對象中。命令模式允許系統使用不同的請求把客戶端參數化。
客戶端代碼:
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);// 決定接收者
Invoker invoker = new Invoker(command);
Invoker.action();
19. 備忘錄模式( Memento )
備忘錄對象是個用來存儲另外一個對象內部狀態的快照的對象。備忘錄模式的用意是在不破壞封裝的條件下,將一個對象的狀態捕捉住,并外部化,存儲起來,從而可以在將來合適的時候把這個對象還原到存儲起來的狀態。
備忘錄角色( Memento ): 1. 將發起人( Originator )對象的內部狀態存儲起來。備忘錄可以根據發起人對象的判斷來決定存儲多少發起人對象的內部狀態。 2 ,可以保護其內容不被發起人對象之外的對象所讀取。備忘錄有兩個等效的接口:
a) ???????? 窄接口:負責人( Caretaker )對象(和其他除發起人對象之外的任何對象)看到的是備忘錄的窄接口,這個窄接口只允許它把備忘錄對象傳給其他對象。
b) ???????? 寬接口:與負責人對象看到的窄接口相反的是,發起人對象可以看到一個寬接口,這個寬接口允許它讀取所有的數據,以便根據這些數據恢復這個發起人對象的內部狀態。
發起人角色( Originator ):創建一個含有當前的內部狀態的備忘錄對象。使用備忘錄對象存儲其內部狀態。
???? 負責人角色( Caretaker ):負責保存備忘錄對象。不檢查備忘錄對象的內容。
20. 狀態模式( State )
狀態模式允許一個對象在其內部狀態改變時候改變其行為。這個對象看上去就像是改變了它的類一樣。
狀態模式和策略模式非常像。如果環境角色只有一個狀態,那么就應當用策略模式。策略模式的特點是:一旦環境角色選擇了一個具體策略類,那么在整個環境類的生命周期里它都不會改變這個具體策略類。而狀態模式則適用于另一個情況,即環境角色有狀態轉移。在環境類的生命周期里面,會有幾個不同的狀態對象被使用。
21. 訪問者模式( visitor )
訪問者模式的目的是封裝一些施加于某種數據結構元素之上的操作。一旦這些操作需要修改的話,接受這個操作的數據結構則可以保持不變。
訪問者模式使得增加新的操作變得很容易。如果一些操作依賴于一個復雜的結構對象的話,那么一般而言,增加新的操作會很復雜。而使用訪問者模式,增加新的操作就意味著增加一個新的訪問者類,因此變得的很容易。訪問者模式將有關的行為集中到一個訪問者對象中,而不是分散到一個個的節點類中。訪問者模式可以路過幾個類的等級結構訪問屬于不兩只的等級結構的成員類中。迭代子只能訪問屬于同一個類型等級結構的成員對象,而不能訪問屬于不同等級結構的對象。訪問者模式可以做到這一點。
訪問者模式的缺點:增加新的節點類變得很困難。每增加一個新的節點都意味著要在抽象訪問者角色中增加一個新的抽象操作,并在每一個具體訪問者類中增加相應的具體操作。破壞封裝,訪問者模式要求訪問者對象訪問并調用每個節點的對象操作,這隱含了一個對所有節點對象的要求:它們必須暴露一些自己的操作和內部狀態。不然,訪問者的訪問就沒有意義。由于訪問者對象自己會積累訪問操作所需要的狀態,從而使這些狀態不再存儲在節點對象中,這也是破壞封裝。
22. 解釋器模式( Interpreter )
給定一個語言之后,解釋器模式可以定義出其文法的一種表示,并同時提供一個解釋器。客商可以使用這個解釋器來解釋這個語言中的句子。
23. 調停者模式( Mediator )
調停者模式包裝了一系列對象相互作用的方式,使得這些對象不必互相明顯引用。從而使它們可以較松散地耦合。當這些對象中的某些對象之間的相互作用發生改變時,不會立即影響到其他的一些對象之間的酵素作用。從而保證這些相互作用可以彼此獨立地變化。
調停者和門面模式很相似。門面模式為一個子系統提供了一個簡單的接口,其中消息的傳送是單方向的,因為門面模式的客戶端只通過門面類向子系統發出消息,而不是相反的情況。調停者模式則不同,它與同事對象的相互作用是多方向的。
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
