# 基礎概念
- 設計模式六大原則
? 設計模式六大原則](http://www.uml.org.cn/sjms/201211023.asp)
? 《研磨設計模式》A2.1章節
? 1. 單一職責原則(SRP)
? ? 一個類應該僅有一個引起它變化的原因。
? 2. 里氏替換原則(LSP)
? ? 凡是基類能使用的地方,子類也一定能使用。
? 3. 依賴倒置原則(DIP)
? ? 要依賴于抽象,不要依賴于具體。
? ? 倒置接口所有權,就是hollywood原則:不要找我們,我們會聯系你。
? 4. 接口隔離原則(ISP)
? ? 接口盡量單一,只代表一個角色。
? 5. 迪米特法則(最少知識原則LOD)
? ? 一個對象應當對其他對象的細節有盡可能少的了解。
? 6. 開閉原則(OCP)
? ? 對擴展開放,對修改關閉。
- 參考資料
? - [23種設計模式](https://www.cnblogs.com/beijiguangyong/archive/2010/11/15/2302807.html)
# 已使用模式匯總
- HystixCommand使用了命令模式。
- Prometheus通過適配器模式使用cratedb。
- 適配器模式實現混合云。
- 告警模塊使用了觀察者模式。
- 對云主機的操作使用命令模式。
- 對菜單和按鈕的管理使用組合模式。
- 在混合云控制器中使用模板方法模式。
- shiro和spring security采用了模板方法模式。
- 計費管理、監控系統用策略模式。
- 處理訂單狀態、審批流程可以使用狀態模式。
- 通過備忘錄模式實現主機創建失敗時的補償操作。
- 解釋器模式,可以解析藍圖定義文件。
- Spring的AOP采用了策略模式,策略是CGLib和JDK動態代理。
# 簡單工廠
簡單工廠,提供一個創建對象實例的功能,而無須關系其具體實現。被創建實例的類型可以是接口、抽象類,也可以是具體的類。
使用簡單工廠前的代碼:
```java
API api = new Impl();
```
編碼時需要知道Impl類。
使用簡單工廠后:
```java
API api = Factory.createAPI();
```
```java
public Class Factory {
? public static API createAPI() {
? ? ? API api = new Impl();
? }
}
```
# 外觀模式
外觀模式,即fa?ade模式,為子系統中的一組接口提供一個一致的界面,fa?ade模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
使用外觀模式前:

使用外觀模式后:

# 工廠方法模式
工廠方法模式(Factory Method),定義一個用于創建對接的接口,讓子類決定實例化哪一個類,Factory Method使一個類的實例化延遲到其子類。
工廠方法模式有點類似IoC。
# 抽象工廠模式
抽象工廠模式(Abstract Factory),提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
# 適配器模式
適配器模式(Adapter),將一個類的接口轉化成客戶希望的另外一個接口。適配器模式使得原來由于接口不兼容而不能一起工作的那些類可以一起工作。
適配器模式中的對象:
Client:客戶端,調用自己需要的領域接口Target。
Target:定義客戶端需要的跟特定領域相關的接口。
Adaptee:已經存在的接口,通常能滿足客戶端的功能要求,但是接口與客戶端要求的特定領域接口不一致,需要被適配。
Adapter:適配器,把Adaptee適配成Client需要的Target。
# 生成器模式
- 定義
? 生成器模式(Builder),又稱為建造者模式,將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
? 生成器模式的本質是分離構建算法和部件構造。
- 生成器模式與模板方法模式
? 兩者有很多類似的地方,但區別也很明顯,首先是模式的目的,生成器模式是用來構建復雜對象的,而模板方法是用來定義算法骨架,尤其是一些復雜的業務功能的處理算法的骨架;其次是模式的實現,生成器模式是采用委托的方法,而模板方法采用的是繼承的方式。
# 原型模式
原型模式(Prototype),用原型實例指定創建對象的種類,并通過拷貝這些原型創建新的對象。
- Java的Cloneable接口
? 調用super.clone的方法的時候,Java先開辟一塊內存空間,然后把實例對象的值原樣拷貝過去。
- 淺度克隆和深度克隆
? 深度克隆都需要自己實現。
# 中介者模式
中介者模式(Mediator),用一個中介對象來封裝一系列的對象交互。中介者使得各對象不需要顯式的相互引用,從而使其耦合松散,而且可以獨立的改變他們之間的交互。
# 代理模式
- 定義
? 代理模式(Proxy),為其他對象提供一種代理以控制對這個對象的訪問。
? Hibernate的Lazy Load就是用代理模式來實現的。
- 靜態代理和動態代理
? 自己實現的代理模式稱為靜態代理,缺點是subject接口發生變化,則代理類和實現類都要發生變化。
? 使用Java內建的對代理模式支持的功能稱為Java的動態代理,動態代理類始終只有一個invoke方法,當subject接口發生變化的時候,動態代理的接口不需要跟著變化。
# 觀察者模式
- 定義
? 觀察者模式(Observer),定義對象間的一種一對多的依賴關系。當一個對象的狀態發生改變時,所有依賴它的對象都得到通知并被自動更新。
- 觀察者模式與訂閱/發布模式的區別
? 觀察者模式:
? 
? 發布訂閱模式:
? 
? 區別在于觀察者模式的具體目標直接持有觀察者對象,在目標對象發生變化時,直接通知觀察者。
? 而發布/訂閱模式存在調度中心,有調度中心統一處理訂閱者注冊到調度中心的處理代碼。
# 命令模式
命令模式(Command),將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化,對請求進行排隊或者記錄請求日志,以及支持可撤銷的操作。
命令模式的好處:
1、 更松散的耦合
使發起命令的對象(客戶端)和具體實現命令的對象(接收者)對象完全解耦
2、 更動態的控制
命令模式把請求封裝起來,可以動態的對它進行參數化、隊列化和日志化、<font color="red">撤銷</font>等操作,從而使得系統更靈活。
3、 很自然的復合操作
命令對象能夠很容易的組合成復合命令,也就是前面講的宏命令,從而使系統操作更簡單,功能更強大。
4、 更好的擴展性
由于發起命令的對象和具體的實現完全解耦,因此擴展新的命令就很容易,只需要實現新的命令對象,然后在裝配的時候,把具體的實現對象設置到命令對象中,然后就可以使用這個命令對象,已有的實現完全不用變化。
# 迭代器模式
迭代器模式(Iterator),提供一種方法順序訪問一個聚合對象中的各個元素,而又不需要暴露該對象的內部表示。
# 組合模式
組合模式(Composite),將對象組合成樹型結構以表示“部分-整體”的層次結構。組合模式使得用戶對單個對象和組合對象的使用具有一致性。
組合模式通過引入一個抽象的組件對象,作為組合對象和葉子對象的父對象,這樣就把組合對象和葉子對象統一起來了,用戶使用的時候,始終是在操作組件對象,而不用去區分操作組合對象還是葉子對象。
# 模板方法模式
模板方法模式(Template Methdod),定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。
# 策略模式
策略模式(strategy),定義一系列的算法,把他們一個個封裝起來,并且使他們可相互替換。本模式使得算法可獨立于它的客戶而變化。
# 狀態模式
狀態模式(state),允許一個對象在其內部狀態改變時改變它的行為。對象看起來似乎修改了它的類。
狀態模式的本質是根據狀態來分離和選擇行為。
# 備忘錄模式
備忘錄模式(memento),在不破壞封裝性的前提下,捕獲一個對象的內部狀態,并在改對象之外保存這個狀態,
備忘錄模式的本質是保護和恢復內部狀態。
- 實現可撤銷操作的兩種方式
? 一種是補償式或者反操作式,比如被撤銷的操作是加的功能,那撤銷的實現就變成減的功能;被撤銷的功能是打開的功能,那撤銷的實現就變成關閉的功能。
? 另一種方式是存儲恢復式,把操作前的狀態記錄下來,要撤銷的時候就直接恢復回去。
# 享元模式
享元模式(flyweight),運用共享技術有效的支持大量細粒度的對象。
對象實例的數據的可變部分稱為外部狀態,不變部分稱為內部狀態。把內部狀態分離出來共享,稱之為享元。
JDK中的Integer、Lang、Byte、String等都用到了享元模式。他們的valueOf()方法用到了享元模式,String常量池就是享元模式。
# 解釋器模式
解釋器模式(interpreter),給定一個語言,定義它的文法的一種表示,并定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。
# 裝飾模式
裝飾模式(Decorator)動態地給一個對象添加一些額外的職責。就增加功能來說,裝飾模式比生成子類更加靈活。
裝飾模式的本質是動態組合。
裝飾模式和AOP的思路類似。
JDK中的InputStream相關類使用了裝飾模式。
# 責任鏈模式
責任鏈模式(chain of responsibility),使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關系。將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理它為止。
# 橋接模式
橋接模式(Bridge),將抽象部分和它的實現部分分離,使他們都可以獨立地變化。
JDK中橋接模式的一個例子是JDBC。
# 訪問者模式
表示一個作用于某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。