首發於個人公衆號html
設計模式圖冊java
主要用於建立對象,包括正則表達式
用於處理類或者對象的組合,包括算法
用於描述類與對象怎樣的交互和分配職責,包括編程
可是因爲職責擴散會致使在實際中每每會有悖於單一職責設計模式
繼承包含這樣一層含義:父類中凡是已經實現好的方法(相對於抽象方法而言),其實是在設定一系列的規範和契約,雖然它不強制要求全部的子類必須聽從這些契約,可是若是子類對這些非抽象方法任意修改,就會對整個繼承體系形成破壞。而里氏替換原則就是表達了這一層含義。安全
繼承做爲面向對象三大特性之一,在給程序設計帶來巨大便利的同時,也帶來了弊端。好比使用繼承會給程序帶來侵入性,程序的可移植性下降,增長了對象間的耦合性,若是一個類被其餘的類所繼承,則當這個類須要修改時,必須考慮到全部的子類,而且父類修改後,全部涉及到子類的功能都有可能會產生故障。數據結構
接口隔離原則跟以前的單一職責原則很類似,其實否則。其一,單一職責原則原注重的是職責;而接口隔離原則注重對接口依賴的隔離。其二,單一職責原則主要是約束類,其次纔是接口和方法,它針對的是程序中的實現和細節;而接口隔離原則主要約束接口接口,主要針對抽象,針對程序總體框架的構建。多線程
採用接口隔離原則對接口進行約束時,要注意如下幾點:架構
運用接口隔離原則,必定要適度,接口設計的過大或太小都很差。設計接口的時候,只有多花些時間去思考和籌劃,才能準確地實踐這一原則。
通俗的來說,就是一個類對本身依賴的類知道的越少越好。也就是說,對於被依賴的類來講,不管邏輯多麼複雜,都儘可能地的將邏輯封裝在類的內部,對外除了提供的public方法,不對外泄漏任何信息, 迪米特法則還有一個更簡單的定義:只與直接的朋友通訊。首先來解釋一下什麼是直接的朋友:每一個對象都會與其餘對象有耦合關係,只要兩個對象之間有耦合關係,咱們就說這兩個對象之間是朋友關係。耦合的方式不少,依賴、關聯、組合、聚合等。其中,咱們稱出現成員變量、方法參數、方法返回值中的類爲直接的朋友,而出如今局部變量中的類則不是直接的朋友。也就是說,陌生的類最好不要做爲局部變量的形式出如今類的內部。
依賴倒置原則基於這樣一個事實:相對於細節的多變性,抽象的東西要穩定的多。以抽象爲基礎搭建起來的架構比以細節爲基礎搭建起來的架構要穩定的多。在java中,抽象指的是接口或者抽象類,細節就是具體的實現類,使用接口或者抽象類的目的是制定好規範和契約,而不去涉及任何具體的操做,把展示細節的任務交給他們的實現類去完成。
依賴倒置原則的核心思想是面向接口編程,
開閉原則無非就是想表達這樣一層意思:用抽象構建框架,用實現擴展細節。由於抽象靈活性好,適應性廣,只要抽象的合理,能夠基本保持軟件架構的穩定。而軟件中易變的細節,咱們用從抽象派生的實現類來進行擴展,當軟件須要發生變化時,咱們只須要根據需求從新派生一個實現類來擴展就能夠了。固然前提是咱們的抽象要合理,要對需求的變動有前瞻性和預見性才行。
用抽象構建框架,用實現擴展細節的注意事項而已:
名稱
|
Factory Method
|
結構
|
![]() |
動機
|
定義一個用於建立對象的接口,讓子類決定實例化哪個類。Factory Method 使一個類的實例化延遲到其子類。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Abstract Factory
|
結構
|
![]() |
動機
|
提供一個建立一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Builder
|
結構
|
![]() |
動機
|
將一個複雜對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Prototype
|
結構
|
![]() |
動機
|
用原型實例指定建立對象的種類,而且經過拷貝這些原型建立新的對象。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Singleton
|
結構
|
![]() |
動機
|
保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
public class BetterSingleton {
private BetterSingleton2() {
}
public static BetterSingleton getInstance() {
return Singleton.BETTER_SINGLETON;
}
public static class Singleton{
private static final BetterSingleton BETTER_SINGLETON = new BetterSingleton();
}
}
複製代碼
模式 | 場景發散 | 一句話歸納 |
---|---|---|
工廠方法(Factory Method) | new太多如何管理 | 生產系列產品。 |
抽象工廠(Abstract Factory) | new太多如何管理 | 一次生產多個不一樣產品。 |
生成器(Builder) | 車手選車 | 生產有不少組件的產品。 |
原型(Prototype) | 複製不能很難 | 克隆對象。 |
單件(Singleton) | 如何管理全局信息 | 全局只有一個。 |
名稱
|
Bridge
|
結構
|
![]() |
動機
|
將抽象部分與它的實現部分分離,使它們均可以獨立地變化。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Flyweight
|
結構
|
![]() |
動機
|
運用共享技術有效地支持大量細粒度的對象。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Facade
|
結構
|
![]() |
動機
|
爲子系統中的一組接口提供一個一致的界面,F a c a d e 模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Decorator
|
結構
|
![]() |
動機
|
動態地給一個對象添加一些額外的職責。就增長功能來講,D e c o r a t o r 模式相比生成子類更爲靈活。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Composite
|
結構
|
![]() |
動機
|
將對象組合成樹形結構以表示?部分-總體?的層次結構。C o m p o s i t e 使得用戶對單個對象和組合對象的使用具備一致性。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Proxy
|
結構
|
![]() |
動機
|
爲其餘對象提供一種代理以控制對這個對象的訪問。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Adapter
|
結構
|
![]() <div data-type="image" data-display="block" data-align="center" data-src="http://www.uml.org.cn/chanpin/intro/WebHelp/Adapter_Class.gif" data-width="543">
<img src="http://www.uml.org.cn/chanpin/intro/WebHelp/Adapter_Class.gif" width="543" />
</div>
</div>
</td>
</tr>
<tr>
<td rowspan="1" colSpan="1">
<div data-type="p">動機</div>
</td>
<td rowspan="1" colSpan="1">
<div data-type="p">將一個類的接口轉換成客戶但願的另一個接口。Adapter 模式使得本來因爲接口不兼容而不能一塊兒工做的那些類能夠一塊兒工做。</div>
</td>
</tr>
<tr>
<td rowspan="1" colSpan="1">
<div data-type="p">適用性</div>
</td>
<td rowspan="1" colSpan="1">
<ul data-type="unordered-list">
<li data-type="list-item" data-list-type="unordered-list">
<div data-type="p">你想使用一個已經存在的類,而它的接口不符合你的需求。</div>
</li>
<li data-type="list-item" data-list-type="unordered-list">
<div data-type="p">你想建立一個能夠複用的類,該類能夠與其餘不相關的類或不可預見的類(即那些接口可能不必定兼容的類)協同工做。</div>
</li>
<li data-type="list-item" data-list-type="unordered-list">
<div data-type="p">(僅適用於對象Adapter )你想使用一些已經存在的子類,可是不可能對每個都進行子類化以匹配它們的接口。對象適配器能夠適配它的父類接口。</div>
</li>
</ul>
</td>
</tr>
<tr height="34px">
<td rowspan="1" colSpan="1">
<div data-type="p">優勢</div>
</td>
<td rowspan="1" colSpan="1">
<ul data-type="unordered-list">
<li data-type="list-item" data-list-type="unordered-list">
<div data-type="p">將目標類和適配者類解耦,經過使用適配器讓不兼容的接口變成了兼容,讓客戶從實現的接口解耦。</div>
</li>
<li data-type="list-item" data-list-type="unordered-list">
<div data-type="p">增長了類的透明性和複用性,將具體的實現封裝在適配者類中,對於客戶端類來講是透明的,並且提升了適配者的複用性。</div>
</li>
<li data-type="list-item" data-list-type="unordered-list">
<div data-type="p">靈活性和擴展性都很是好在不修改原有代碼的基礎上增長新的適配器類,符合「開閉原則」。</div>
</li>
</ul>
</td>
</tr>
<tr height="34px">
<td rowspan="1" colSpan="1">
<div data-type="p">缺點</div>
</td>
<td rowspan="1" colSpan="1">
<ul data-type="unordered-list">
<li data-type="list-item" data-list-type="unordered-list">
<div data-type="p">過多地使用適配器,會讓系統很是零亂,不易總體進行把握。好比,明明看到調用的是 A 接口,其實內部被適配成了 B 接口的實現,一個系統若是太多出現這種狀況,無異於一場災難。</div>
</li>
<li data-type="list-item" data-list-type="unordered-list">
<div data-type="p">所以若是不是頗有必要,能夠不使用適配器,而是直接對系統進行重構。</div>
</li>
</ul>
</td>
</tr>
<tr height="34px">
<td rowspan="1" colSpan="1">
<div data-type="p">小結</div>
</td>
<td rowspan="1" colSpan="1">
<ul data-type="unordered-list">
<li data-type="list-item" data-list-type="unordered-list">
<div data-type="p">當咱們須要使用的一個現有的類,可是他的接口並不符合咱們的需求時,咱們可使用適配器模式。</div>
</li>
<li data-type="list-item" data-list-type="unordered-list">
<div data-type="p">適配器模式分爲類適配器和對象適配器,其中類適配器須要用到多重繼承。</div>
</li>
</ul>
</td>
</tr>
</tbody>
複製代碼
|
模式 | 場景發散 | 一句話說明 |
---|---|---|
橋(Bridge) | 麻煩的日誌記錄 | 將「抽象」和「實現」自由搭配。 |
輕量(Flyweight) | 森林裏的樹太多了 | 輕鬆地處理「大量」對象。 |
外觀(Façade) | 超級手機 | 同時提供簡單接口和複雜接口。 |
裝飾者(Decorator) | 星巴克的飲料計較系統 | 不改變接口但要加強功能。 |
組合(Composite) | 超酷的繪圖軟件 | 無論你是老子仍是兒子,都同樣處理。 |
代理(Proxy) | 找中介租房 | 代理要控制你的訪問,同時讓你的訪問更舒服 。 |
適配器(Adapter) | 老掉牙系統的重生 | 不改變功能但要改變接口 |
名稱
|
Observer
|
結構
|
![]() |
動機
|
定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時, 全部依賴於它的對象都獲得通知並被自動更新。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Strategy
|
結構
|
![]() |
動機
|
定義一系列的算法,把它們一個個封裝起來, 而且使它們可相互替換。本模式使得算法可獨立於使用它的客戶而變化。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Iterator
|
結構
|
![]() |
動機
|
提供一種方法順序訪問一個聚合對象中各個元素, 而又不需暴露該對象的內部表示。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Command
|
結構
|
![]() |
動機
|
將一個請求封裝爲一個對象,從而使你可用不一樣的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可撤消的操做。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Visitor
|
結構
|
![]() |
動機
|
表示一個做用於某對象結構中的各元素的操做。它使你能夠在不改變各元素的類的前提下定義做用於這些元素的新操做。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Interpreter
|
結構
|
![]() |
動機
|
給定一個語言,定義它的文法的一種表示,並定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Mediator
|
結構
|
![]() |
動機
|
用一箇中介對象來封裝一系列的對象交互。中介者使各對象不須要顯式地相互引用,從而使其耦合鬆散,並且能夠獨立地改變它們之間的交互。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Mediator
|
結構
|
![]() |
動機
|
用一箇中介對象來封裝一系列的對象交互。中介者使各對象不須要顯式地相互引用,從而使其耦合鬆散,並且能夠獨立地改變它們之間的交互。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Template Method
|
結構
|
![]() |
動機
|
定義一個操做中的算法的骨架,而將一些步驟延遲到子類中。Te m p l a t e M e t h o d 使得子類能夠不改變一個算法的結構便可重定義該算法的某些特定步驟。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
State
|
結構
|
![]() |
動機
|
容許一個對象在其內部狀態改變時改變它的行爲。對象看起來彷佛修改了它的類。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
名稱
|
Chain of Responsibility
|
結構
|
![]() |
動機
|
使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關係。將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它爲止。
|
適用性
|
|
優勢
|
|
缺點
|
|
小結
|
|
模式 | 場景發散 | 一句話說明 |
---|---|---|
觀察者(Observer) | 同步更新的問題 | 一呼百應。 |
策略(Strategy) | 設計你的戰士 | 分離算法。 |
迭代器(Iterator) | 集合訪問的煩惱 | 以一致的方式訪問集合, 「鬆綁 」遍歷算法代碼。 |
命令(Command) | 神奇的Do與Undo | 分離功能調用者與功能實現者。 |
訪問者(Visitor) | 增長新方法的煩惱 | 不改變對象結構增長新方法。 |
解釋器(Interpreter) | 超級表達解釋引擎 | 語法解釋。 |
中介者(Mediator) | 麻煩的多角關係 | 處理多對多關係。 |
備忘錄(Memento) | 假如一切能夠重來 | 保存對象的多個狀態並可任意恢復。 |
模板方法(Template Method) | 萬能的排序器 | 定義好框架算法 ,某些步驟可本身定義 。 |
狀態(State) | 是攻擊仍是逃走 | 方便地處理不一樣狀態不一樣行爲,以及狀態之間的轉換。 |
責任鏈(Chain) | 郵件自動處理系統 | 用不一樣的規則去處理請求。 |
《硬啃設計模式》
《HeadFirst 設計模式》
GoF 《可複用面向對象軟件的基礎》
歡迎關注個人公衆號,一塊兒學習,共同提升~
複製代碼