1. 程式人生 > >《headfirst設計模式》筆記

《headfirst設計模式》筆記

總結

基礎

抽象

封裝

多型

繼承

原則

封裝變化

多用組合,少用繼承

針對介面程式設計,不針對實現程式設計

為互動物件之間的鬆耦合設計而努力

對擴充套件開放,對修改關閉

依賴抽象,不要依賴具體類

只和朋友交流

別找我,我會找你

類應該只有一個改變的理由

模式

策略模式

策略模式,定義演算法族,分別封裝起來,讓它們之間可以互相替換,此模式讓演算法的變化獨立於使用演算法的客戶。

觀察者模式

在物件之間定義一對多的依賴,這樣一來,當這個物件改變狀態,依賴它的物件都會受到通知,並自動更新。代表MVC

裝飾者模式

動態將責任附加到物件上,想要擴充套件功能,裝飾者提供有別於繼承的另一種選擇。代表JAVA中IO(INPUTStream系列)

抽象工廠模式

提供一個介面,用於建立相關或依賴物件的家族,而不需要明確指定具體類。

工廠方法模式

定義了一個建立物件的介面,但由子類決定要例項化的類是哪一個。工廠方法讓類把例項化推遲到子類。

單例模式

確保一個類只有一個例項,並提供全域性訪問點。

命令模式

將請求封裝成物件,這可以讓你使用不同的請求、佇列、或者日誌請求來引數化其物件。命令模式也可以支援撤銷操作

介面卡模式

將一個類的介面,轉換成客戶期望的另一個介面。介面卡讓原本不相容的類可以合作無間

外觀模式(門面模式)

提供了一個統一的介面,用來訪問子系統中的一群介面。外觀定義了一個高層介面,讓子系統更加容易使用。

模板方法模式(Template)

在一個方法中定義了一個演算法的骨架,而將一些步驟延遲到子類中。模板方法使的子類可以在不改變演算法的結構的情況下,重新定義演算法中的某一些步驟。

迭代器模式(Iterator)

提供一種方法順序訪問一個聚合物件中各個元素,而又不暴露其內部的表示

組合模式(Composite)

執行你將物件組成樹形結構表現“整體/部分”的層次結構。組合能讓客戶以一致的方式處理個別對象和物件組合。

狀態模式(STATE)

允許物件在內部狀態改變時改變它的行為,物件看起來好像修改了它的類

代理模式(proxy)

為另一個物件提供一個替身或佔位符以訪問這個物件

複合模式

複合模式結合兩個或以上的模式,組成一個解決方案,解決一再發生的一般性問題。

設計模式入門

使用模式對的最好方式:把模式裝進腦子裡,然後在你的設計和已有的應用中,尋找何處可以使用他們。

  1. 找出應用中可能需要變化之處,把他們獨立出來,不要和那些不需要變化的程式碼混在一起。
  2. 針對介面程式設計,而不是針對實現程式設計。針對介面程式設計,就是針對超型別程式設計。
  3. 變數的宣告應該是超型別:比如抽象類或者一個介面。
  4. 有一個(組合)可能比是一個更好
  5. 多用組合,少用繼承.類的行為不是通過繼承得到而是通過組合得到的。

策略模式(Strategy)

定義了演算法族,分別封裝起來,讓他們之間可以互相替換,此模式讓演算法的變化獨立於使用演算法的客戶。

類的行為就可以看做是演算法

觀察者模式(Observe)讓你的物件知悉現況

類比報紙、雜誌的訂閱

觀察者模式

定義了物件之間的一對多依賴,這樣一來,當一個物件改變狀態時,它的所有依賴者都會收到通知並自動更新。 Swing大量使用觀察者模式,許多GUI框架也是如此。

java內建觀察者模式

JAVA API有內建的觀察者模式。java.util包內包含了最基本的Observer介面與Observable類,甚至可以使用推拉模式。

可觀察者如何送出通知

  1. 先呼叫setChanged()方法,標記狀態已經改變的事實
  2. 然後呼叫兩種notifyObservers()方法中的一個:notifyObservers()或notifyObservers(Object arg),這個版本可以傳送任何資料物件給每一個觀察者

觀察者如何接受通知

觀察者實現了更新方法,但是方法的簽名不一樣。

update(Observable o,Object arg)
1. Observable:主題本身當做第一個變數,好讓觀察者知道是哪個主題通知它的。
2. arg這正是傳入notifyObservers()的資料,如果沒有說明則為空

setChanged()方法用來標記狀態已經改變的事實,好讓notifyObservers()知道當它被呼叫時應該更新觀察者。如果呼叫notifyObservers()之前沒有先呼叫setchanged(),觀察者就不會被通知。

java.util.Observable的暗黑面
Observable是以類,不是介面,必須被繼承。
setChanged()方法是protect的,只有繼承才能呼叫。

裝飾者模式(Decorator)

類應該對拓展開放,對修改關閉

舉例:以飲料為主體,然後執行時以調料來“裝飾”飲料。

  1. 裝飾者和被裝飾者物件有相同的超型別。
  2. 你可以用一個或多個裝飾者包裝一個物件
  3. 裝飾者可以在所委託被裝飾者的行為之前或之後,加上自己的行為
  4. 物件可以在任何時候被裝飾

裝飾者模式

動態地將責任附加到物件上,若有拓展功能,裝飾者提供了比繼承更有彈性的替代方案。 真實世界的裝飾者:java I/O

裝飾者模式缺點

有大量的小類,數量比較多

原則

對拓展開放,對修改關閉

工廠模式(Factory)

利用靜態方法定義一個簡單的工廠,這是很常見的技巧,常被稱為靜態工廠。為何使用靜態方法?因為不需要使用建立物件的方法來例項化物件。但是有一個缺點,不能通過繼承來改變建立方法的行為

定義簡單工廠

簡單工廠其實不是一個設計模式,應該算是一種程式設計習慣。 設計模式中,所謂“實現一個介面”並不一定表是寫一個類,並利用implement關鍵字來實現某個Java介面。“實現一個介面”泛指實現某個超型別(可以試類或介面)

所有工廠模式都用來封裝物件的建立。工廠方法模式(Factory Method Pattern)通過讓子類決定該建立的物件是什麼,來達到將物件建立的過程封裝的目的。

定義工廠方法模式

工廠方法模式:定義一個建立物件的介面,但由子類決定要例項化的類是哪一個。工廠方法讓類把例項化推遲到子類

簡單工廠把全部的事情,在一個地方都處理完了,然而工廠方法卻是建立一個框架,讓子類決定要如何實心。簡單工廠的做法,是將物件的建立封裝起來,簡單工廠不具備工廠方法的彈性。

要依賴抽象,不要依賴具體類

多依賴抽象類,而不依賴具體類。 依賴倒置:是底層元件依賴於抽象高層的抽象。

定義抽象工廠模式

抽象工廠模式:提供一個介面,用於建立相關或依賴物件的家族,而不需要明確指定具體類

總結

依賴抽象,不要依賴具體類

  1. 所有的工廠都是用來封裝物件的建立
  2. 簡單工廠,雖然不是真正的涉及模式,但是也是一個簡單的方法,實現將客戶程式從具體類解耦
  3. 工廠方法使用繼承:把物件的建立委託給子類,子類實現工廠方法來建立物件
  4. 抽象工廠使用物件的組合:物件的建立被實現在工廠介面所暴露出來的方法中
  5. 抽象工廠建立相關的物件家族,而不需要依賴它們具體類。
  6. 簡單理解就是抽象工廠由多個工廠方法組成

單例模式(singleton)

用來建立獨一無二的,只能有一個例項的物件。比如執行緒池、記憶體、配置表。

單例模式也提供一個全域性訪問點,和全域性變數。但是不是程式一開始就建立物件。
JVM實現:在用到的時候才建立物件

經典的單間模式實現

public class Singleton{
    private static Singleton uniqueInstance;//利用靜態變數記錄唯一例項
    private Singleton(){//私有構造器宣告為私有,只有Singleton類才可以呼叫構造器
        
    }
    public static Singleton getInstance(){
        if(uniqueInstance == null){
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }
    
}

如果我們不需要這個例項,它就永遠不會產生

單例模式

確保一個類只有一個例項,並提供一個全域性訪問點

處理多執行緒問題

把getInstance()變成同步(synchronized)方法,就可以解決多執行緒

public class Singleton{
    private static Singleton uniqueInstance;
    private Singleton(){}
    public static synchronized Singleton getInstance(){
        if(uniqueInstance == null){
            uniqueInstance = new Singleton();
        }
        return uniqeuInstance;
    }
}

誠然,這種方式會影響效能。可以有如下選擇:

  1. 如果getInstance()的效能對應用程式不是很關鍵,就什麼都別做。這樣做簡單高效
  2. 如果建立單例,對程式負擔不重,就不用延遲例項化的做法
pulbic static Singleton uniqueInstance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
    return uniqueInstance;
}
  1. 用雙重檢查加鎖,在getInstance()中減少使用同步 利用雙重檢查加鎖,首先檢查是否建立了,未建立,才進行同步,只有一次同步機會。
public class Singleton{
    private volatile static Singleton uniqueInstance;
    private Singleton(){}
    public static Singleton getInstance(){
        if(uniqueInstance==null){
            synchronized(Singleton.class){
                if(uniqueInstance==null){
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}

注意:volatile關鍵字確保:當uniqueInstance變數被初始化,多個執行緒能處理uniqueInstance變數。必須在1.5及以上才能使用。

關於多個類載入器可能有機會各自建立自己的單價例項

每個類載入器都定義了一個名稱空間。如果有兩個以上的類載入器,不同的類載入器可能會載入同一個類,從整個程式來看,同一個類會被載入多次。如果是單例模式的類,就會產生多個單例並存。解決辦法:自行指定類載入器,並指定同一個類載入器。

java1.2以後單例模式不會被垃圾回收器回收。放心使用

總結

  1. 單例模式確保程式中一個類最多隻有一個例項
  2. 單例模式也是提供訪問這個例項的全域性點
  3. 在java實現單例模式需要私有構造器、一個靜態方法和一個靜態變數
  4. 確定在效能和資源的限制上,小心選擇適當的方案來實現單例。
  5. 如果不是採用java 5以上,雙重檢查會失效。
  6. 使用JVM1.2或之前的版本,必須建立單件登錄檔,以免垃圾收集器將單件回收

命令模式(command)——封裝呼叫

將方法呼叫(method invocation)封裝起來 通過封裝方法呼叫哦,可以記錄日誌、或者實現撤銷undo 命令模式可以將“動作的請求者”從“動作的執行者”物件中解耦

命令模式

將“請求”封裝成物件,以便使用不同的請求、佇列或者日誌來引數化其他物件。命令模式也支援可撤銷操作。

在許多設計模式中都會看到空物件的使用。甚至有些時候,空物件本身也被視為是一種設計模式

總結

  1. 命令模式將發出請求的物件和執行請求的物件解耦
  2. 在被解耦的兩者之間是通過命令物件進行溝通的。命令物件封裝了接受者的一個或一組動作
  3. 呼叫者通過呼叫命令物件的excute()發出請求,這會使得接受者的動作被呼叫
  4. 呼叫者可以接受命令當做引數,甚至在執行時動態地進行
  5. 命令可以支援撤銷,做法是實現一個undo()方法來回到excute()被執行前的狀態。
  6. 巨集命令是命令的一種簡單延伸,允許呼叫多個命令。巨集方法也可以支援撤銷
  7. 實際操作時,很常見使用命令物件,也可以直接實現請求,而不是將工作委託給接受者。
  8. 命令可以用來實現日誌和事物系統。

介面卡模式(Adapter)與外觀模式(Facade,也叫門面模式)

裝飾者模式將物件包裝起來,並賦予它們新的職責。而現在是將某些物件包裝起來,將類的介面轉換成自己想要的介面

需要讓一個介面卡包裝多個被適配者,這就是外觀模式

定義介面卡模式

將一個類的介面,轉換成客戶期望的另一介面。介面卡讓原本介面不相容的類可以合作無間。

1. 類介面卡使用多重繼承,物件介面卡使用組合
2. 物件介面卡使用組合,可以適配該類的任何子類
3. 

裝飾者和介面卡

  1. 當事情涉及到裝飾者,就表示一些新的行為或責任要加入到你的設計中。
外觀模式和介面卡模式的差異不在於它們包裝了幾個類,而是在於它們的意圖,介面卡模式的意圖是“改變”介面符合客戶的期望;而外觀模式的意圖是提供子系統的一個簡化介面。

定義外觀模式

提供一個統一的介面,用來訪問子系統中的一群介面。外觀定義了一個高層介面,讓子系統更容易使用。

最少知識原則

告訴我們要減少物件之間的互動,只留下幾個密友

總結

  1. 當需要使用一個現有的類而其介面不符合我的需求時,就使用介面卡
  2. 當需要簡化並統一一個很大的介面或者一群複雜的介面時,使用外觀
  3. 介面卡改變介面以符合客戶的期望
  4. 外觀將客戶從一個複雜的子系統中解耦
  5. 實現一個介面卡可能需要一番功夫,與目標介面的大小和複雜程度有關
  6. 實現一個外觀,需要將子系統組合進外觀中,然後將工作委託給子系統來執行
  7. 介面卡模式有兩種形式:物件介面卡和類介面卡。類介面卡需要用到多重繼承
  8. 你可以為一個子系統實現一個以上的外觀
  9. 介面卡將一個物件包裝起來以改變其介面;裝飾者將一個物件包裝起來以增加新的行為和責任,而外觀將一群物件“包裝”起來以簡化介面。

模板方法模式 封裝演算法(Template)

直到目前,我們議題都繞著封裝轉;我們已經封裝了物件的建立、方法的呼叫、複雜介面。接下來我們要封裝演算法塊

模板方法定義了一個演算法的步驟,並允許子類為一個或多個步驟提供實現

定義模板方法模式

在一個方法中定義了一個演算法的骨架,而將一些步驟延遲到子類中。模板方法使的子類可以在不改變演算法結構的情況下,重新定義演算法中的某些步驟

1. 當你的子類必須提供演算法中的某個方法或步驟的實現時,就使用抽象方法。如果演算法的這個部分是可選的,就使用鉤子,如果是鉤子的話,子類可以選擇實現這個鉤子
2. 好萊塢法則:別調用高層,讓高層選擇呼叫
3. applet大量使用了模板方法模式

總結

  1. 模板方法定義了演算法的步驟,把這些步驟的實現延遲到了子類
  2. 模板方法模式為我們提供了一種程式碼複用的重要技巧。
  3. 模板方法的抽象類可以定義具體方法、抽象方法和鉤子
  4. 抽象方法由子類實現
  5. 鉤子是一種方法,它在抽象類中不做事,或者只做預設的事情,子類可以選擇要不要去覆蓋它
  6. 為了防止子類改變模板方法中的演算法,可以將模板方法宣告為final
  7. 好萊塢原則告訴我們,將決策權放在高層模組中,以便決定如何以及何時呼叫底層模組
  8. 策略模式和模板方法模式都封裝演算法,一個用組合一個用繼承
  9. 工廠方法是模板方法的一種特殊版本

管理良好的集合 迭代器(Iterator)與組合模式(Composite)

封裝變化的部分

1. 如果不允許一個方法,可以丟擲一個java.lang.UnsupportedOperationException執行時異常

定義迭代器模式

提供一種方法順序訪問一個聚合物件中的各個元素,而又不暴露其內部的表示。 迭代器模式把元素之間的遊走的責任交給迭代器,而不是聚合物件。這不僅讓聚合的介面和實現變得更簡潔,也可以讓聚合更專注在它所應該專注的事情上面

迭代器意味著沒有次序。只是取出所有的元素,並不表示取出元素的先後就代表元素的大小次序。對於迭代器來說,資料結構可以有次序或是沒有次序,甚至資料是可以重複的。除非某個集合檔案有特別說明,否則不可以對迭代器所取出的元素大小順序做出假設

單一責任

類的每個責任都有改變的潛在區域。超過一個責任,意味著超過一個改變的區域。這個原則告訴我們,儘量讓每個類保持單一責任

#### java5的迭代器和集合
java5中包含了一種新形式的for語句,稱為for/in.這可以讓你在一個集合或者一個數組中遍歷,而且不需要顯式建立迭代器
```
for(Object:collection){
    
}
```

定義組合模式(composite)

允許你將物件組合成樹形結構來表現“整體/部分”層次結構。組合能讓客戶以一致的方式處理個別對象以及物件組合

使用組合結構,我們能把相同的操作應用在組合和個別物件上。換句話說,在大多數情況下,我們可以忽略物件組合和個別物件之間的差別

總結

  1. 迭代器允許訪問聚合的元素,而不需要暴露它的內部結構
  2. 迭代器將遍歷聚合的工作封裝進一個物件中。
  3. 當使用迭代器的時候,我們依賴聚合提供遍歷
  4. 迭代器提供了一個通用的介面,讓我們遍歷聚合的項時,就可以使用多型機制
  5. 組合模式提供一個結構,可同時包容個別物件和組合物件
  6. 組合模式允許客戶對個別物件以及組合物件一視同仁
  7. 組合結構內的任意物件稱為元件,元件可以是組合,也可以是葉節點

狀態模式(事物的狀態)state

狀態通過改變物件內部的狀態來幫助物件控制自己的行為

定義狀態模式

允許物件在內部狀態改變時改變它的行為,物件看起來好像修改了它的類

將狀態封裝稱為獨立的類,並將動作委託到代表當前狀態的物件,我們知道行為會隨著內部狀態而改變

總結

  1. 狀態模式允許一個物件基於內部狀態而擁有不同的行為
  2. 和程式狀態機PSM不同,狀態模式用類代表狀態
  3. Context會將行為委託給當前狀態物件
  4. 通過將每個狀態封裝進一個類,我們把以後需要做的任何改變發區域性化了
  5. 狀態模式和策略模式有相同的類圖,但是它們的意圖不同
  6. 策略模式通常會用行為或演算法來配置Context類
  7. 狀態模式允許Context隨著狀態的改變而改變行為
  8. 狀態轉換可以由STATE類或Context類控制
  9. 使用狀態模式通常會導致設計中類的數目大量增加
  10. 狀態類可以被過個Context例項共享

代理模式(Proxy)控制物件的訪問

代理要做的就是:控制和管理訪問 遠端物件:是一種物件,活在不同java虛擬機器(JVM)堆中或者說,在不同的地址空間執行的遠端物件

製作遠端服務

  1. 製作遠端介面 遠端介面定義出可以讓客戶遠端呼叫的方法
  2. 製作遠端實現 為遠端介面中定義遠端方法提供真正的實現
  3. 利用rmic產生的stub和skeleton。這是客戶和服務的輔助類,不需要建立這些類
  4. 啟動RMI registry 可以從中查詢代理的位置
  5. 開始遠端服務 服務實現類去例項化一個服務的例項,並將這個服務註冊到RMI registry

製作遠端介面

  1. 拓展java.rmi.Remote remote不具有方法,只是一個標記
  2. 宣告所有的方法都會丟擲RemoteException
  3. 確定變數和返回值屬於原語型別或者序列化型別。遠端方法的變數和返回值,必須屬於原語型別或Serializable型別。這不難理解。遠端方法的變數必須被打包並通過網路運送,這要靠序列化來完成。如果你使用原語型別、字串和許多API中內定的型別,都不會有問題。如果你傳送自己定義的類,就必須保證你的類實現了Serializable

製作遠端實現

  1. 實現遠端介面 你的服務必須實現遠端介面,也就是客戶將要呼叫的方法介面
  2. 拓展UnicastRemoteObject 為了要成為遠端服務物件,你的物件需要某些“遠端”功能。最簡單的就是拓展UnicastRemoteObject,讓超類幫你做這些工作
  3. 設計一個不帶變數的構造器,並宣告RemoteException
  4. 用RMI REgistry註冊此服務 當註冊這個實現物件時,RMI系統其實註冊的是stub,因為這是客戶真正需要的。註冊服務使用了java.rmi.Naming類的靜態rebind()方法

產生Stub和Skeleton

在遠端實現類上執行rmic rmic 是JDK內一個工具,用來為一個服務類產生stub和skeleton。

執行remiregistry

開啟一個終端,啟動remiregistry

啟動服務

開啟另一個終端,啟動服務

工作方式

  1. 客戶到RMI registry中尋找
Naming.lookup("rmi://127.0.0.1/RemoteHello")
  1. RMI registry返回Stub物件 作為lookup方法的返回值,然後RMI會自動對Stub反序列化。你在客戶端必須有stub類,否則stub就無法被反序列化
  2. 客戶呼叫stub的方法,就像stub就是真正的服務物件一樣
注意:
1. 忘了在啟動遠端服務之前先啟動rmiregistry
2. 忘了讓變數和返回值的型別成為可序列化的型別
3. 忘了給客戶提供stub類

transient關鍵字,這樣就告訴JVM不要序列化這個欄位

定義代理模式

為另一個物件提供一個替身或佔位符以控制對這個物件的訪問。 控制訪問是客戶端不知道如何訪問真正的物件。

幾種代理控制訪問的方式
1. 遠端代理控制訪問遠端物件
2. 虛擬代理控制訪問建立開銷大的資源
3. 保護代理基於許可權控制對資源的訪問

虛擬代理作為建立開銷大的物件的代表。虛擬代理經常直到我們真正需要一個物件的時候才建立它。當物件在建立前和建立中時,由虛擬代理來扮演物件的替身。物件建立後,代理就會將請求直接委託給物件。

使用JAVA API代理建立保護代理

java在java.lang.reflect包中有自己的代理支援,利用這個包你可以在執行時動態地建立一個代理類,實現一個或多個介面,並將方法的呼叫轉發到你所指定的類。動態代理,需要執行方法放在InvocationHandler中。

要點

  1. 代理模式為另一個物件提供代表,以便控制客戶對物件的訪問,管理訪問的方式有許多種
  2. 遠端代理管理客戶和遠端物件之間的互動
  3. 虛擬代理控制訪問示例化開銷大的物件
  4. 保護代理基於呼叫者控制對物件方法的訪問
  5. 代理模式有許多變體,例如:快取代理、同步代理、防火牆代理和寫入時複製代理
  6. 代理在結構上類似裝飾者
  7. 裝飾者模式為物件加上行為,而代理則是控制訪問
  8. java內建的代理支援,可以根據需要建立動態代理,並將所有呼叫分配到所選的處理器
  9. 和其他的包裝者(wrapper)一樣,代理會造成你的設計中類的數目增加

複合模式 模式的模式

由不同模式構成模式。複合模式代表是MVC 複合模式在一個解決方案中結合兩個或多個模式,以解決一般或重複發生的問題。 MVC是數個模式的結合

MVC模式

  1. 模型利用觀察者讓控制器和檢視可以隨最新的狀態改變而更新。控制器是檢視的行為
  2. 檢視和控制器實現了經典的策略模式:檢視是一個物件,可以被調整使用不同的策略,而控制器提供了策略。 Model 2是MVC在WEB上的調整

總結

  1. mvc是複合模式,結合了觀察者模式、策略模式和組合模式
  2. 模型使用了觀察者模式,以便觀察者更新,同時保持兩者之間的解耦
  3. 控制器是檢視的策略,檢視可以使用不同的控制器實現,得到不同的行為
  4. 檢視使用組合模式實現使用者介面,使用者介面通常組合了巢狀的元件,像面板、框架和按鈕
  5. 這些模式攜手合作,把MVC模型的三層解耦,保持設計乾淨又有彈性
  6. 介面卡模式用來將新的模型適配成已有的檢視和控制器
  7. model2是MVC在web上的應用,在model2中,控制器實現成Servlet,而JSP/html是檢視

複合模式

複合模式結合兩個及兩個或以上的模式,組成一個解決方案,解決一再發生的一般性問題。

與設計模式相處——真實世界中的模式

模式

在某情景下,針對某問題的某種解決方案

  1. 情景就是應用某個模式的情況,這應該是會不斷出現的情況
  2. 問題就是你想在某情景下達到的目標,但也可以是某情景下的約束
  3. 解決方案就是你所追求的,一個通用的設計。

建立型模式

建立型模式涉及到將物件例項化,這類模式都提供一個方法,將客戶從所需要例項化的物件中解耦

行為型模式

都涉及到類和物件如何互動及分配職責

結構型模式

可以讓你把類或物件組合到更大的結構中

保持簡單

設計時,儘可能用最簡單的方式解決問題,你的目標應該是簡單

重構的時間就是模式的時間

重構就是通過改變你的程式碼來改進它的組織方式的過程。目標是要改善其結構而不是其行為。應該將思緒集中在設計本身,而不是模式上,只有真正需要時才使用模式,有些時候簡單的方式就行得通,那麼就不要用模式

反模式

告訴你如何採用一個不好的解決方案解決一個問題。反模式看起來總像是一個好的解決方案,但是當它真正被採用後,就會帶來麻煩。通過將反模式歸檔,我們能夠幫助其他人在實現它們之前,分辨出不好的解決方案。 反模式有它自己的誘惑,但是在長遠來看會造成不好的影響。反模式除了告訴你不好之外,也給你提出建議的解決方案。

  1. 模式能夠帶來最大的好處之一是:讓你的團隊擁有共享詞彙。

其它模式

橋接模式(Bridge)

使用橋接模式不只改變你的實現,也改變你的抽象

責任鏈模式(Chain of Responsibility Pattern)

當你想要讓一個以上的物件有機會能夠處理某個請求的時候,就使用責任鏈模式

享元模式(蠅量模式 Flyweight Pattern)

如想讓某個類的一個例項能用來提供許多“虛擬例項”,就使用享元模式。 享元模式的用途和缺點

  1. 當一個類有許多的例項,而這些例項能被同一方法控制的時候,我們就可以使用享元模式
  2. 享元模式的缺點在於,一旦你實現了它,那麼單個邏輯例項將無法擁有獨立而不同的行為。

中介者 (Mediator pattern)

使用中介者模式(Mediator Pattern)來集中相關物件之間的複雜的溝通和控制方式。

中介者的優點
1. 通過將物件彼此解耦,可以增加物件的複用性
2. 通過將控制邏輯集中,可以簡化系統維護
3. 可以讓物件之間所傳遞的訊息變得簡單而且大幅減少
中介者的用途和缺點
1. 中介者常常被用來協調相關的GUI元件
2. 中介者模式的缺點是,如果設計不當,中介者物件本身會變的過於複雜

備忘錄(Memento Pattern)

當你需要讓物件返回之前的狀態時(例如,你的使用者請求“撤銷”),就使用備忘錄模式

備忘錄的用途和缺點
1. 備忘錄用於儲存狀態
2. 使用備忘錄的缺點:儲存和恢復狀態的過程可能相當耗時
3. 在java系統中,其實可以考慮使用序列化機制儲存系統的狀態

原型模式(prototype)

當建立給定類的例項的過程很昂貴或很複雜時,就使用原型模式

訪問者模式

當你想要為一個物件的組合增加新的能力,且封裝並不重要時,就使用訪問者模式(Visitor Pattern)

訪問者的優點

1. 允許你對組合結構加入新的操作,而無需改變結構本身。
2. 想要加入新的操作,相對容易
3. 訪問者所進行的操作,其程式碼是集中在一起的

訪問者的用途和缺點

1.  當採用訪問者模式的時候,就會打破組合類的封裝
2.  因為遊走的功能牽涉其中,所以對組合結構的改變就更加困難