23種設計模式--概要總結

一、設計模式的六大原則

總原則---開閉原則:

對于拓展是開放的,對于修改是封閉的。即對于一個功能的拓展不應該是通過修改原來的代碼實現,而是應該通過添加新代碼實現。但有時這個情況也是不可避免的。

1. 單一職責原則

對于一個類而言,應該僅有一個引起它變化的原因。

2. 里氏替換原則

子類型必須能夠替換掉它們的父類型。只有子類能替換掉父類,軟件單位的功能不受影響時,父類才能真正被復用,而子類也能夠在父類的基礎上增加新的行為。

3. 依賴倒轉原則

開閉原則的基礎。原話:抽象不應該依賴細節,細節應該依賴于抽象。即針對接口編程。同時高層模塊不應該依賴底層模塊,兩者都應該依賴于抽象。

4. 接口隔離原則

每個接口中不存在子類用不到卻必須實現的方法,如果不然,就要將接口拆分。使用多個隔離的接口,比使用單個接口(多個接口方法集合到一個的接口)要好。

5. 迪米特法則(最少知道原則)

如果兩個類不必彼此直接通信,那么這兩個類就不應當發生直接的相互作用。如果其中一個類需要調用另一個類的某一個方法的話,可以通過第三者轉發這個調用。

6. 合成/聚合復用原則

盡量優先使用合成/聚合的方式,而不是繼承。這樣子有助于保持每個類被封裝,并被集中在單個任務上。這樣類和類繼承層次會保持較小規模,并且不太可能增長為不受控制的龐然大物。

二、創建型模式

1. 簡單工廠模式(該模式不屬于23種模式中的)

通過簡單的一個工廠類來創建相應的對象,將生成產品類的代碼跟客戶端代碼分離,但與此同時,其違反了開閉原則(因為每增加一個產品類都需修改工廠了)。

2. 工廠方法模式(Factory Method)

定義: 定義一個用于創建對象的接口,讓子類決定實例化哪個類。工廠方法使一個類的實例化延遲到其子類。

只有一個抽象產品類和一個抽象工廠類。每個具體工廠類只能實例化一個具體產品類。克服了簡單工廠模式違背開閉原則的弊端,通過創建一個工廠接口,每次新增產品,則新建一個工廠類實現該接口即可。但當產品類過多時,也會帶來工廠類過多的弊端。

3. 抽象工廠模式(Abstract Factory)

定義: 提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。

具有多個抽象產品類和一個抽象工廠類。每個具體工廠類可以實例化多個具體產品類。符合開閉原則。

與工廠方法模式的區別:工廠方法模式只有一個抽象產品類,而抽象工廠模式有多個。工廠方法模式的具體工廠類只能創建一個具體產品類的實例,而抽象工廠模式可以創建多個。工廠方法用于創建 "一種" 產品,著重點在于"怎么創建"。抽象工廠則是創建一系列產品,著重點在于"創建哪些"產品上。

4. 建造者模式(Builder)

定義: 將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。


普通建造者模式的結構圖

Android中存在一種通過靜態內部類(Builder)等方式實現的對象屬性的無序化構造的建造者模式,Android中的對話框多用此種形式創建。

5. 單例模式

定義:保證一個類只有一個實例,并提供一個訪問它的全局訪問點。


單例模式結構圖

單例模式的八種寫法比較

6. 原型模式(Prototype)

定義:用原型實例指定創建對象的種類,并通過拷貝這些原型創建新的對象。


原型模式結構圖

由于該模式十分常用,故java中已經提供了該模式的相關實現。java中復制分為淺復制和深復制。

  • 淺復制:將一個對象復制后,基本數據類型的變量都會重新創建,而引用類型,指向的還是原對象所指向的。
  • 深復制:將一個對象復制后,不論是基本數據類型還有引用類型,都是重新創建的。簡單來說,就是深復制進行了完全徹底的復制,而淺復制不徹底。
/* 相應的對象要實現Cloneable和Serializable接口
    Cloneable接口是空方法,clone和deepClone等方法的名字可以隨便起
*/
/* 淺復制 */
public Object clone() throws CloneNotSupportedException {
    return super.clone();
}

/* 深復制(通過序列化,也可通過直接創建新對象實現) */
public Object deepClone() throws IOException, ClassNotFoundException {

    /* 寫入當前對象的二進制流 */
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(this);

    /* 讀出二進制流產生的新對象 */
    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
    ObjectInputStream ois = new ObjectInputStream(bis);
    return ois.readObject();
}

三、結構型模式

7種結構型模式:適配器模式、裝飾模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。其中對象的適配器模式是各種模式的起源


結構型模式導圖

1. 適配器模式(Adapter)

定義: 將一個類的接口轉換成客戶希望的另外一個接口。該模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作


對象適配器結構圖

該模式有兩種,類適配器對象適配器。在GoF的設計模式中,類適配器是通過多重繼承來實現的,但java不支持多重繼承,所以在這里結構圖給出的是對象適配器的。該模式一般在軟件開發后期或者維護期再考慮使用。

2. 橋接模式(Bridge)

定義: 將抽象部分與它的實現部分分離,使它們都可以獨立地變化。(抽象與它的實現分離,并不是指讓抽象類和其派生類分離,實現指的是抽象類和它的派生類用來實現自己的對象)


橋接模式結構圖

通俗理解:實現系統可能有多角度的分類,每一種分類都有可能變化,那么就把這種多角度分離出來讓它們獨立變化,減少它們之間的耦合。利于拓展。

舉例:手機可以按照手機品牌分類,每種品牌下有其各自品牌的手機軟件。


舉例圖

手機也可以按照手機軟件分類,每種軟件下有各個品牌的手機軟件。


舉例圖

所以我們可以將品牌和軟件進行分離,得到如下的結構:


示意圖

這種結構就是橋接模式,其核心就是把這些實現獨立出來,讓它們各自地變化,使其不會相互影響,達到應對變化的目的。否則,每當我們需要新增品牌或者軟件時,都要新建許多類。

3. 組合模式(Composite)

定義:將對象組合成樹形結構以表示 '部分-整體' 的層次結構。組合模式使得用戶對單個對象和組合對象的使用具有一致性


組合模式結構圖

組合模式分為安全組合模式透明(一致性)組合模式

透明方式指的是Component中聲明所有用來管理子對象的方法,其中包括Add、Remove等,優點是葉子節點和枝節點對于外界沒有區別,具備完全一致的行為接口,缺點是葉子節點實現Add、Remove等方法沒有意義。

安全方式指的是Component中不聲明Add、Remove等方法,而是在Composite中聲明所有用來管理子類對象的方法,缺點是樹葉和樹枝類不具有相同的接口,客戶端的調用需要做相應的判斷。

使用場景:需求中體現了部分與整體層次的結構,或者可以忽略組合對象與單個對象的不同,統一地使用組合結構中的所以對象時。

4. 裝飾模式(Decorator)

定義: 動態地給對象增加一些額外的職責,就增加功能來說,裝飾模式比生成子類更為靈活。


裝飾模式結構圖

優點:將類中的裝飾功能從類中搬移去除,起到簡化原有的類的作用。更大的好處是有效的把類的核心職責和裝飾功能區分開,并可以去除相關類中重復的裝飾邏輯。

5. 外觀模式(Facade)

定義: 為子系統中的一組接口提供一個一致的界面,此模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。


外觀模式結構圖

外觀模式將類與類之間的關系集中到Facade類中一起管理,降低了類與類之間的耦合度。該模式完美的體現了依賴倒轉原則迪米特法則

使用場景
設計初期階段,應有意識的分離不同的層,在層與層之間建立外觀,降低耦合。
開發階段,子系統因為不斷的重構演化越來越復雜,大部分模式使用時也會產生很多很小的類,增加外觀可以提供一個簡單的接口,減少它們之間的依賴。
系統維護階段,舊系統難以維護和拓展,可以為舊系統開發一個外觀Facade類,讓新系統與Facade對象交互,Facade與遺留代碼交互所有復雜的工作。

6. 享元模式(Flyweight)

定義: 運用共享技術有效地支持大量細粒度的對象


享元模式結構圖

FlyWeightFactory負責創建和管理享元單元,當一個客戶端請求時,工廠需要檢查當前對象池中是否有符合條件的對象,如果有,就返回已經存在的對象,如果沒有,則創建一個新對象,FlyWeight是超類或者接口。

內部狀態:在享元對象內部并且不會隨環境改變而改變的共享部分,稱為享元對象的內部狀態。
外部狀態:在享元對象內部并且會隨環境改變而改變的不能共享的部分,稱為享元對象的外部狀態。

應用場景

  • 如果一個應用程序使用了大量的對象,而大量的這些對象造成了很大的存儲開銷時可以考慮使用;
  • 還有就是對象的大多數狀態為外部狀態,如果刪除對象的外部狀態,可以用相對較少的共享對象取代很多對象,可以考慮使用

7. 代理模式(Proxy)

定義: 為其它對象提供一種代理以控制對這個對象的訪問。


代理模式結構圖

應用場景
遠程代理:為一個對象在不同的地址空間提供局部代表,隱藏一個對象存在于不同地址空間的事實。
虛擬代理:根據需要創建開銷很大的對象,通過它來存放實例化需要很長時間的真實對象。
安全代理:用來控制真實對象訪問時的權限
智能指引: 當調用真實對象時,代理處理另外一些事情。

四、行為型模式

第一類:通過父類與子類的關系進行實現。
第二類:兩個類之間。
第三類:類的狀態。
第四類:通過中間類

行為型模式分類

1. 策略模式(Strategy)

定義: 定義了算法家族,分別封裝起來,讓它們之間可以相互替換,此模式讓算法的變化,不會影響到使用算法的客戶。


策略模式結構圖

優點:減少了各種算法類與使用算法類之間的耦合;Strategy類層次為Context定義了一系列可供重用的算法或行為,繼承有助于析取出這些算法中的公共功能;簡化了單元測試,每個算法都有自己類,可以通過自己的接口單獨測試。

基本的策略模式中,選擇所用具體實現的職責由客戶端對象承擔,并轉給Context對象。也可與簡單工廠模式結合,由Context承擔該職責。

策略模式與工廠的區別

2. 職責鏈模式(Chain of Responsibility)

定義:使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關系。將這個對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理它為止。


職責鏈模式結構圖

特別的,在一個時刻,命令只允許由一個對象傳給另一個對象,而不允許傳給多個對象

優點:接收者和發送者都沒有雙方的明確信息,且鏈中的對象自己也不知道鏈的結構。結果是職責鏈可簡化對象的相互連接,它們僅需保持一個指向其后繼者的引用,而不需保持它所有的候選接收這點引用;可以隨時增加或修改處理一個請求的結構,增強了給對象指派職責的靈活性。

3. 命令模式(Command)

定義: 將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化,對請求排隊或則記錄請求日志,以及支持可撤銷的操作。


命令模式結構圖

優點:較容易設計一個命令隊列;需要時,較容易將命令記入日志;允許接收請求一方決定是否要否決請求;容易實現對請求的撤銷和重做;容易增加具體命令類;把請求一個操作的對象與知道怎么執行一個操作的對象分割開。

4. 解釋器模式(Interpreter)

定義: 給定一個語言,定義它的文法的一種表示,并定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。


解釋器模式結構圖

優點:容易改變和拓展文法,因為該模式使用類來表示文法規則,可使用繼承來改變或者拓展文法,也比較容易實現文法,因為定義抽象語法樹中各個節點的類的實現大體類似,都易于直接編寫

缺點:該模式為文法中的每一條規則至少定義了一個類,因為當文法包含許多規則時可能難以管理和維護。文法復雜時,一般使用語法分析程序或者編譯器生成器來處理。

5. 迭代器模式(Iterator)

定義: 提供一種方法順序訪問一個聚合對象中各個元素,而又不暴露該對象的內部表示。


迭代器模式結構圖

迭代器模式就是分離了集合對象的遍歷行為,抽象出一個迭代器來負責,這樣既可以做到不暴露集合的內部結構,又讓外部代碼透明地訪問集合內部的數據。

6. 中介者模式(Mediator)

定義: 用一個中介對象來封裝一系列的對象交互。中介者使各對象不需要顯式地相互引用,從而使其耦合松散,而且可以獨立的改變它們之間的交互。


中介者模式結構圖

優點:Mediator的出現減少了各個Colleague的耦合,使得可以獨立的改變和復用各個Colleague類和Mediator;由于把對象如何協作進行了抽象,將中介作為一個獨立的概念并將其封裝在一個對象中,把關注的重點從對象各自本身的行為轉移到它們之間的交互上來,能站在更宏觀的角度去看待系統。

缺點:由于ConcreteMediator控制了集中化,交互的復雜性變為了中介者的復雜性,會使得中介者變得比任何一個ConcreteColleague都復雜。

應用場景:一搬應用于一組對象以定義良好但是復雜的方式進行通信的場合。以及想定制一個分布在多個類中的行為,而又不想生成太多的子類的場合。

7. 備忘錄模式(Mememto)

定義: 在不破壞封裝性的前提下,捕獲一個對象的內部狀態,并在該對象之外保存這個狀態。這樣以后就可將該對象恢復到原先保存的狀態。


備忘錄模式結構圖

Memento有兩個接口,CareTaker只能看到Memento的窄接口,它只能將備忘錄傳遞給其它對象。Originator能看到一個寬接口,允許它訪問返回到先前狀態所需的所有數據。

應用場景:比較適用于功能比較復雜的,但需要維護和記錄屬性歷史的類。

8. 觀察者模式(Observer)

定義: 定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態發生改變時,會通知所有觀察者對象,使它們能夠自動更新自己。


觀察者模式結構圖

使用場景:當一個對象的改變需要同時改變其它對象時,且它不知道具體有多少對象有待改變;

9. 訪問者模式(Visitor)

定義: 表示一個作用于某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用于這些新元素的操作。


訪問者模式結構圖

訪問者模式適用于數據結構相對穩定的系統。目的在于把數據結構和作用于結構上的操作之間的耦合解脫開,使得操作集合可以相對自由地演化(增加或刪除等)。

如果系統具有比較穩定的數據結構,又有易于變化的算法,則比較適合使用該模式。反之數據結構對象易于變化,則不適合。

事實上,很難找到數據結構不變化的情況,所以該模式使用較少。大多數情況并不需要使用該模式,但當一旦你需要該模式,那就是真的需要了。

優點:利于增加新的操作,因為增加新的操作意味著增加一個新的訪問者。訪問者模式將有關的行為集中到一個訪問者對象中。

缺點:難以增加新的數據結構。

10. 狀態模式(State)

定義: 當一個對象的內部狀態改變時允許改變其行為,這個對象看起來像是改變了其類。


狀態模式結構圖

該模式主要解決的是當控制一個對象狀態轉換的條件表達式過于復雜時,把狀態的判斷轉移邏輯遷移到表示不同狀態的一系列類中,簡化復雜的判斷邏輯。

優點:將與特定狀態相關的行為局部化,并且將不同狀態的行為分割開來

使用場景:當一個對象的行為取決于它的狀態,并且它必須在運行時刻根據狀態改變它的行為時。

11. 模板方法模式

定義: 定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。


模板方法模式結構圖

優點:通過將不變行為搬移到超類,去除了子類中的重復代碼。

參考資料:
《大話數據結構》
23種設計模式全解析
結合實例分析簡單工廠模式&工廠方法模式&抽象工廠模式的區別

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。