我認爲,本章是重點中的重點。並不是23個模式都被普遍應用,其中經常使用和最爲有效的大概有15個模式。前端
一、適配器(Adapter)算法
1)、使用場景數據庫
使用一個已經存在的類,但若是他的接口,也就是他的方法和你的要求不相同時,考慮使用是適配器模式。
就是說,雙方都不修改本身的代碼的時候,能夠採用適配器模式。
2)、結構圖ide
3)、相關模式this
外觀對象:隱藏外部系統的資源適配器也被視爲外觀對象,由於資源適配器使用單一對象封裝了對子系統或系統的訪問。
資源適配器:當包裝對象時爲不一樣外部接口提供適配時,該對象叫資源適配器
4)、準則spa
類名後綴爲「Adapter」。
5)、用到的GRASP原則3d
二、工廠模式日誌
1)、使用場景code
該模式也常稱爲「簡單工廠」或「具體工廠」。如: 1)、存在複雜建立邏輯 2)、爲提升內聚而分離建立者職責(關注點分離) 所以,建立稱爲工廠的純虛構對象來處理這些建立職責。
2)、結構server
通常xxxFactory應該是單實例類。
3)、相關模式
一般使用 單例模式 來訪問工廠模式。
由誰建立工廠呢?通常採用單例模式。
三、單例模式
1)、使用場景
只有惟一實例的類即爲「單實例類」。對象須要全局可見性和單點訪問。
所以,建議對類定義靜態方法用以返回單實例。
2)、相關模式
單例模式:一般用於建立工廠對象和外觀對象
以上整合例子:
四、策略模式
1)、使用場景
銷售的訂價策略(也可叫作規則、政策或算法)具備多樣性。在一段時間內,對於全部的銷售可能會有10%的折扣,後期可能會對超出200元的銷售給予10%的折扣,而且還會存在其餘大量的變化。
所以,在單獨的類中分別定義每種策略/規則/政策/算法,而且使其具備共同接口。
2 )、結構
策略模式,共同的方法內傳入的參數,一般是上下文對象,上圖就是sale。
3)、結合工廠模式
1)、使用工廠模式建立這些策略類
2)、使用單例模式建立工廠類。
五、組合模式
1)、使用場景
若是有重疊怎麼辦?好比: 1)老年人折扣20% 2)購物金額滿200元享受15%折扣 所以,如何可以處理像原子對象同樣,(多態的)處理一組對象或具備組合結構的對象呢? 答:定義組合和原子對象的類,使他們具備相同的接口。
2)、結構
2)、相關模式
一般與策略和命令模式一塊兒使用。
六、外觀模式
1)、使用場景
對一組徹底不一樣的實現或接口(如子系統中的實現和接口)須要公共、統一的接口,隱藏掉子系統複雜的實現或接口。從而使關注點分離。
如:slf4j、通訊前置
其與適配器的區別在於,facade模式針對同職能接口的抽象並提供公共、統一的接口,強度的是統一。而adapter模式針對的是適配不一樣接口且老接口不改的場景,強調的是適配。
2)、結構
3)、例子
class Program { static void Main(string[] args) { Facade facade = new Facade(); facade.MethodA(); facade.MethodB(); Console.Read(); } } class SubSystemOne { public void MethodOne() { Console.WriteLine(" 子系統方法一"); } } class SubSystemTwo { public void MethodTwo() { Console.WriteLine(" 子系統方法二"); } } class SubSystemThree { public void MethodThree() { Console.WriteLine(" 子系統方法三"); } } class SubSystemFour { public void MethodFour() { Console.WriteLine(" 子系統方法四"); } } class Facade { SubSystemOne one; SubSystemTwo two; SubSystemThree three; SubSystemFour four; public Facade() { one = new SubSystemOne(); two = new SubSystemTwo(); three = new SubSystemThree(); four = new SubSystemFour(); } public void MethodA() { Console.WriteLine("\n方法組A() ---- "); one.MethodOne(); two.MethodTwo(); four.MethodFour(); } public void MethodB() { Console.WriteLine("\n方法組B() ---- "); two.MethodTwo(); three.MethodThree(); } }
4)、相關模式
外觀模式一般經過單例模式訪問。
七、觀察者模式(Observer)
1)、定義
觀察者模式又叫「發佈-訂閱(Publish/Subscribe)」模式、又叫「委派事件模型」。
之因此被稱爲觀察者模式,是由於監聽器或訂閱者在對相應事件進行觀察。
之因此被稱爲委派事件模型,是由於發佈者將事件處理委派給了監聽器(訂閱者)
2)、使用場景
例子:支付成功後, 1)記錄日誌 2)寫數據庫 3)前端展現支付結果 傳統方式,將以上3個關注點耦合在一塊兒寫。隨着業務需求愈來愈多,致使很難維護。
總結:當一個對象的改變須要同時改變其餘對象時,並且還不知道有多少對象有待改變時,應該考慮使用觀察者模式。
3)、結構
4)、例子
public abstract class Subject { private List<Observer> observers = new ArrayList<Observer>(); //增長觀察者 public void attach(Observer observer) { observers.add(observer); } //移除觀察者 public void detach(Observer observer) { observers.remove(observer); } //通知 public void notify1() { observers.forEach(o->o.update()); } } public abstract class Observer { public abstract void update(); } public class ConcreteSubject extends Subject { private String subjectState; public String getSubjectState() { return subjectState; } public void setSubjectState(String subjectState) { this.subjectState = subjectState; } } public class ConcreteObserver extends Observer { private String name; private String observerState; private ConcreteSubject subject; public ConcreteObserver( ConcreteSubject subject,String name) { this.subject = subject; this.name = name; } @Override public void update() { observerState = subject.getSubjectState(); System.out.println("觀察者"+name+"的新狀態是"+observerState); } public ConcreteSubject getSubject() { return subject; } public void setSubject(ConcreteSubject subject) { this.subject = subject; } } public class Main { public static void main(String[] args) { ConcreteSubject s = new ConcreteSubject(); s.attach(new ConcreteObserver(s, "X")); s.attach(new ConcreteObserver(s, "Y")); s.attach(new ConcreteObserver(s, "Z")); s.setSubjectState("ABC"); s.notify1(); } } --輸出 觀察者X的新狀態是ABC 觀察者Y的新狀態是ABC 觀察者Z的新狀態是ABC
5)、小結
A、一個事件支持多個訂閱者
public static void main(String[] args) { ConcreteSubject s = new ConcreteSubject(); //多個訂閱者 s.attach(new ConcreteObserver(s, "X")); s.attach(new ConcreteObserver(s, "Y")); s.attach(new ConcreteObserver(s, "Z")); //一個事件 s.setSubjectState("ABC"); s.notify1(); }
B、訂閱者可動態添加或刪除
public abstract class Subject { private List<Observer> observers = new ArrayList<Observer>(); //增長觀察者 public void attach(Observer observer) { observers.add(observer); } //移除觀察者 public void detach(Observer observer) { observers.remove(observer); } //通知 public void notify1() { observers.forEach(o->o.update()); } }