設計模式 — 終章.

1、剩下的模式

一、橋接模式(Bridge Pattern)

  • 概念:不僅改變你的實現,也改變你的抽象。橋接模式的主要特色是把抽象(Abstraction)與行爲實現(Implementation)分離開來,從而能夠保持各部分的獨立性以及應對他們的功能擴展。
  • 角色:
     1. 實現類接口(Implementor):定義行爲實現接口。
     2. 具體實現類(ConcreteImplementor):實現 Implementor 接口,提供不一樣的行爲實現。
     3. 橋接抽象類(Abstraction):用於定義抽象類的接口,它通常是抽象類而不是接口,其中定義了一個Implementor(實現類接口)類型的對象並能夠維護該對象,它與Implementor之間具備關聯關係,它既能夠包含抽象業務方法,也能夠包含具體業務方法。
     4. 擴充抽象類(RefinedAbstraction):擴充由 Abstraction 定義的接口,一般狀況下它再也不是抽象類而是具體類,它實現了在 Abstraction 中聲明的抽象業務方法,在 RefinedAbstraction 中能夠調用在 Implementor 中定義的業務方法。
  • UML圖:
    java

  • 優勢:將抽象與行爲實現解耦,兩者能夠獨立擴展,不會影響到對方。
  • 適用場景:當須要使用不一樣的方式改變接口和實現時。
  • Demo 實現:https://github.com/JMCuixy/design-patterns/tree/master/src/main/java/com/example/bridgegit

二、建造者模式(Builder Pattern)

  • 概念:封裝一個產品的構造過程,並容許按步驟構造。建造者模式能夠將一個產品的內部表象與產品的生成過程分割開來,從而使一個建造過程生成具備不一樣的內部表象的產品對象。
  • 角色:
     1. 抽象建造者(Builder):給出一個抽象接口,以規範產品對象的各個組成成分的建造。
     2. 具體建造者(Concrete Builder):實現 Builder 角色提供的接口,一步一步完成建立產品實例的過程;在建造過程完成後,提供產品的實例。
     3. 指導者(Director):與客戶端打交道,調用具體建造者角色以建立產品對象,指導者並無產品類的具體知識。
     4. 產品(Product):具體建造者構建的複雜對象。
  • UML圖:
    github

  • 優勢:
     1. 將一個複雜對象的建立過程封裝起來;向客戶隱藏產品內部的實現。
     2. 容許對象經過多個步驟來建立,而且能夠改變過程(這和只有一個步驟的工廠模式不一樣)。
     3. 產品的實現能夠被替換,由於客戶只看到一個抽象的接口。
  • 建造者模式和模板方法模式的比較區別?
     1. 建造者是使用組合方式實現不一樣的表示,而模板方法使用的是繼承的方式。
     2. 建造者抽象的是構建過程,而模板方法提取的是實現公共。
  • Demo 實現:https://github.com/JMCuixy/design-patterns/tree/master/src/main/java/com/example/builder編程

三、責任鏈模式(Chain of Responsibility Pattern)

  • 概念:讓一個以上的對象有機會可以處理某個請求。責任鏈模式爲請求建立了一條接收者對象的鏈,每一個接收者都包含對另外一個接收者的引用,當某個接受者不能處理該請求時,會將該請求轉給下一個接受者處理。
  • 角色:
     1. 抽象請求處理者(Handler):是全部具體請求處理者的父類。
     2. 具體請求處理者(Concrete Handler):實現抽象請求處理者,包含下一個具體請求處理者的引用。
  • UML圖:
    設計模式

  • 優勢:
     1. 弱化了發出請求的人和處理請求的人之間的關係。發出請求的人只須要向第一個具體的處理者發送請求,而後就能夠不用管了,處理者會在責任鏈上本身尋找處理的方法。
     2. 經過改變鏈內的成員或調動他們的次序,容許你動態地新增或刪除責任。
  • 缺點:請求須要在責任鏈上傳播責任,直至找到合適的處理對象。這樣雖然提升了程序的靈活性,但同時也出現了處理的延遲。
  • 應用場景:在視窗系統中,常常會使用到責任鏈模式,尤爲是事件的處理,熟悉 javaScript 開發的朋友,可能會知道,瀏覽器中的事件有冒泡機制,就是事件的是向父控件傳播的,若是本身處理不了,就會傳播給父控件去處理。
  • Demo 實現:https://github.com/JMCuixy/design-patterns/tree/master/src/main/java/com/example/chain_of_responsibility瀏覽器

tips:Struts 的攔截器,Servlet 的過濾器,Netty 的 ChannelPipeline 都是責任鏈模式~數據結構

四、蠅量模式(Flyweight Pattern)

  • 概念:讓某個類的一個實例能用來提供許多「虛擬實例」。蠅量模式主要用於減小建立對象的數量,以減小內存佔用和提升性能。蠅量模式嘗試重用現有的同類對象,若是未找到匹配的對象,則建立新對象。
  • 角色:
     1. 抽象蠅量(Flyweight):定義了對蠅量對象外部狀態的操做接口。使用該接口,可在Client中修改蠅量對象的外部狀態。
     2. 可共享內部狀態的具體蠅量(ConcreteFlyweight):維護能夠共享的內部狀態;實現操做外部狀態的接口。
     3. 無可共享內部狀態的具體蠅量(UnsharedConcreteFlyweight):無內部狀態,因此只實現操做外部狀態的接口。
     4. 蠅量工廠(FlyweightFactory):負責管理蠅量對象,造成一個對象池,提供對取出對象的方法,取出時若池中對象足夠,就直接返回,若對象不足則建立後返回。
  • UML:
    編程語言

  • 優勢:
     1. 減小運行時對象實例的個數,節省內存。
     2. 將許多「虛擬」對象(可共享內部狀態的具體蠅量)的狀態集中管理。
  • 缺點:單個的邏輯實例將沒法擁有獨立而不一樣的行爲。
  • 應用場景:當一個類有許多的實例,而這些實例能被同一方法控制的時候。
  • Demo 實現:https://github.com/JMCuixy/design-patterns/tree/master/src/main/java/com/example/flyweight函數

五、解釋器模式(Interpreter Pattern)

  • 概念:給定一個語言,定義它的文法的一種表示,並定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。
  • 角色:
     1. 抽象表達式(Expression):聲明一個全部的具體表達式都須要實現的抽象接口;這個接口主要是一個interpret()方法,稱作解釋操做。
     2. 終結符表達式(Terminal Expression):終結符表達式,實現了抽象表達式所要求的接口;文法中的每個終結符都有一個具體終結表達式與之相對應。好比公式 R = R1 + R2,R1 和 R2 就是終結符,對應的解析 R1 和 R2 的解釋器就是終結符表達式。
     3. 非終結符表達式(Nonterminal Expression):文法中的每一條規則都須要一個具體的非終結符表達式,非終結符表達式通常是文法中的運算符或者其餘關鍵字,好比公式 R = R1 + R2 中,「+"就是非終結符,解析「+」的解釋器就是一個非終結符表達式。
     4. 上下文(Context):它的任務通常是用來存放文法中各個終結符所對應的具體值,好比 R = R1 + R2,給 R1 賦值100,給 R2 賦值200,這些信息須要存放到上下文中。
  • UML:
    工具

  • 優勢:
     1. 將每個語法規則表示成一個類,方便於實現語言。
     2. 由於語法由許多類表示,因此你能夠輕易的改變或者擴展此語言。
     3. 經過在類結構中加入新的方法,能夠在解釋的同時增長新的行爲。例如打印格式的美化或者進行復雜的程序驗證。
  • 應用場景:
     1. 解釋器模式在日常使用的較少,能夠用來處理腳本語言和編程語言。
     2. 當你須要實現一個簡單的語言時,或者簡單比效率更重要時,使用解釋器模式。
  • Demo 實現:https://github.com/JMCuixy/design-patterns/tree/master/src/main/java/com/example/interpreter

六、中介者模式(Mediator Pattern)

  • 概念:來集中相關對象之間複雜的溝通和控制方式。中介者模式定義了一箇中介對象來封裝一系列對象之間的交互關係。中介者使各個對象之間不須要顯式地相互引用,從而使耦合性下降,並且能夠獨立地改變它們之間的交互行爲。
  • 角色:
      1. 抽象中介者(Mediator)角色:它是中介者的接口,提供了同事對象註冊與轉發同事對象信息的抽象方法。
      2. 具體中介者(ConcreteMediator)角色:實現中介者接口,定義一個 List 來管理同事對象,協調各個同事角色之間的交互關係,所以它依賴於同事角色。
      3. 抽象同事類(Colleague)角色:定義同事類的接口,保存中介者對象,提供同事對象交互的抽象方法,實現全部相互影響的同事類的公共功能。
      4. 具體同事類(Concrete Colleague)角色:是抽象同事類的實現者,當須要與其餘同事對象交互時,由中介者對象負責後續的交互。
  • UML:

  • 優勢:
     1. 經過將對象彼此解耦,能夠增長對象的複用性。
     2. 經過將控制邏輯集中,能夠簡化系統維護。
     3. 將對象間的一對多關聯轉變爲一對一的關聯,可讓對象之間所傳遞的消息變得簡單並且大幅減小。
  • 缺點:若是設計不當,中介者對象自己會變得過於複雜。
  • 應用場景:
     1. 中介者模式經常被用來協調相關的 GUI 組件。
     2. 當一組對象要進行溝通或者業務上的交互,可是其關係卻又很複雜混亂時。
  • Demo 實現:https://github.com/JMCuixy/design-patterns/tree/master/src/main/java/com/example/mediator

七、備忘錄模式(Memento Pattern)

  • 概念:在不破壞封閉的前提下,捕獲一個對象的內部狀態,並在該對象以外保存這個狀態。備忘錄模式的目標包括:儲存系統關鍵對象的重要狀態;維護關鍵對象的封裝。
  • 角色:
     1. 備忘錄(Memento)角色:備忘錄角色存儲「備忘發起角色」的內部狀態。「備忘發起角色」根據須要決定備忘錄角色存儲「備忘發起角色」的哪些內部狀態。爲了防止「備忘發起角色」之外的其餘對象訪問備忘錄。備忘錄實際上有兩個接口,「備忘錄管理者角色」只能看到備忘錄提供的窄接口——對於備忘錄角色中存放的屬性是不可見的。「備忘發起角色」則可以看到一個寬接口——可以獲得本身放入備忘錄角色中屬性。
     2. 備忘發起(Originator)角色:「備忘發起角色」建立一個備忘錄,用以記錄當前時刻它的內部狀態。在須要時使用備忘錄恢復內部狀態。
     3. 備忘錄管理者(Caretaker)角色:負責保存好備忘錄。不能對備忘錄的內容進行操做或檢查。
  • UML:

  • 優勢:
     1. 將被存儲的狀態放在外面,不要和關鍵對象混在一塊兒,這能夠幫助維護內聚。
     2. 保持關鍵對象的數據封裝。
     3. 提供了容易實現的恢復能力。
  • 缺點和應用場景:
     1. 備忘錄用於存儲狀態。
     2. 儲存和恢復狀態的過程可能至關耗時。
     3. 在 Java 系統中,其實能夠考慮使用序列化機制儲存系統的狀態。
  • Demo 實現:https://github.com/JMCuixy/design-patterns/tree/master/src/main/java/com/example/memento

八、原型模式(ProtoType Pattern)

  • 概念:容許經過複製現有的實例來建立新的實例(在 Java 中,這一般意味着使用 clone() 方法,或者反序列化)。這個模式的重點在於,客戶的代碼在不知道要實例化何種特定類的狀況下,能夠製造出新的實例。
  • 角色:
     1. 抽象原型類(Prototype):聲明克隆自身的接口。在 java 中就是 Cloneable 接口。
     2. 具體原型類(ConcretePrototype):實現克隆的具體操做。
  • UML:

  • 優勢:
     1. 向客戶隱藏製造新實例的複雜性。
     2. 提供讓客戶可以產生未知類型對象的選項。
     3. 在某些環境下,複製對象比建立新對象更有效。
  • 用途和缺點:
     1. 在一個複雜的類層次中,當系統必須從其中的許多類型建立新對象時,能夠考慮原型。
     2. 使用原型模式的缺點:對象的複製有時至關複雜(淺拷貝和深拷貝)。
  • Demo 實現:https://github.com/JMCuixy/design-patterns/tree/master/src/main/java/com/example/prototype

九、訪問者模式(Visitor Pattern)

  • 概念:爲一個對象的組合增長新的能力,且封裝並不重要時。訪問者模式將做用於某種數據結構中的各元素的操做分離出來封裝成獨立的類,使其在不改變數據結構的前提下能夠添加做用於這些元素的新的操做,爲數據結構中的每一個元素提供多種訪問方式。它將對數據的操做與數據結構進行分離,是行爲類模式中最複雜的一種模式。
  • 角色:
     1. 抽象訪問者(Visitor)角色:定義一個訪問具體元素的接口,爲每一個具體元素類對應一個訪問操做 visit() ,該操做中的參數類型標識了被訪問的具體元素。
     2. 具體訪問者(ConcreteVisitor)角色:實現抽象訪問者角色中聲明的各個訪問操做,肯定訪問者訪問一個元素時該作什麼。
     3. 抽象元素(Element)角色:聲明一個包含接受操做 accept() 的接口,被接受的訪問者對象做爲 accept() 方法的參數。
     4. 具體元素(ConcreteElement)角色:實現抽象元素角色提供的 accept() 操做,其方法體一般都是 visitor.visit(this) ,另外具體元素中可能還包含自己業務邏輯的相關操做。
     5. 對象結構(Object Structure)角色:是一個包含元素角色的容器,提供讓訪問者對象遍歷容器中的全部元素的方法,一般由 List、Set、Map 等聚合類實現。
  • UML:

  • 優勢:
     1. 容許你對組合結構加入新的操做,而無需改變結構自己。
     2. 想要加入新的行爲,相對容易。
     3. 訪問者所進行的操做,其代碼是集中在一塊兒的。
  • 缺點:
     1. 當採用訪問者模式的時候,就會打破組合類的封裝。
     2. 由於遊走的功能牽涉其中,因此對組合結構的改變就更加困難。
     3. 違反了依賴倒置原則。訪問者模式依賴了具體類,而沒有依賴抽象類。
  • Demo 實現:https://github.com/JMCuixy/design-patterns/tree/master/src/main/java/com/example/visitor

2、其餘

一、複合模式

  • 複合模式:在一個解決方案中結合兩個或多個模式,以解決通常或重複發生的問題。
  • MVC 是複合模式,結合了觀察者模式、策略模式和組合模式(視圖)。這些模式攜手合做,把 MVC 模型的三層解耦,這樣能夠保持設計乾淨又有彈性。
  • 模型使用觀察者模式,以便觀察者(視圖)更新,同時保持二者之間解耦。
  • 控制器是視圖的策略,視圖可使用不一樣的控制器實現,獲得不一樣的行爲。
  • Model 2是 MVC 在 Web 上的應用。
  • 在Model 2中,控制器實現成 Servlet,而 JSP/HTML 是實現視圖。

二、設計模式概論

  • 模式是在某情境(context)下,針對某問題的某種解決方案。設計模式是解決一個常常重複發生的設計問題。
  • 模式不是法律或準則,模式只是指導方針,你能夠改變模式來符合你的須要,真實世界中的許多實例,都不符合經典的設計模式。
  • 請務必牢記在心,模式是被「發現的」,而不是被建立的。因此,任何人均可能發現某個設計模式,而後寫出它的描述。
  • 通常來講,必需要經過「三次準則」,纔算是一個合格的模式。也就是說,只有在真實世界中被應用三次以上,才能算是一個模式。
  • 根據模式的目標,咱們將設計模式分紅三個不一樣的類目:建立型、行爲型(對象之間的溝通和互聯)和結構型(動態的組合對象):

  • 模式只是一種工具,只有在須要時才使用這種工具,而咱們時刻要遵照的是模式中的設計原則。
  • 儘量地用最簡單的方式解決問題,不要刻意去使用設計模式!當你在設計的時候,若是肯定在你的設計中能夠利用某個模式解決某個問題,那麼就使用這個模式!若是有更簡單的解決方案,那麼在決定使用模式以前應該先考慮這個方案。
  • 有一種狀況,即便有更簡單的解決方案,你仍然想要使用模式,這種狀況就是:你預期系統在將來會發生改變,可是務必要肯定一件事,這個改變是可能發生的實際改變,而不是假想的改變。
  • 模式可能帶來複雜性,可能致使代碼被過分工程化,若是沒有必要,咱們毫不須要這樣的複雜性。

三、設計原則

  • 單一職責原則(single responsibility principle,SPR):一個類負責一項職責。
  • 開閉原則(Open-Close Principe,OCP):一個軟件實體如類、模塊和函數應該對擴展開放,對修改關閉。
  • 里氏替換原則(Liskov Substitution Principe,LSP):一個軟件實體若是使用的是一個父類的話,那麼必定適用於其餘子類,二且他察覺不出父類對象和子類對象的區別。
  • 依賴倒置原則(Dependence Inversion Principle):高層模塊不該該依賴低層模塊,兩者都應該依賴其抽象;抽象不該該依賴細節;細節應該依賴抽象。即針對接口編程,不要針對實現編程。
  • 接口隔離原則(Interface Segregation Principle, ISP):創建單一接口,不要創建龐大臃腫的接口,儘可能細化接口,接口中的方法儘可能少。
  • 迪米特法則(Law of Demeter,LoD):最少知識原則,清掉了類之間的鬆耦合,下降了系統的耦合度。
  • 組合/聚合複用原則(Composite Reuse Principe,CRP):儘可能使用組合和聚合少使用繼承的關係來達到複用的原則。

四、反模式

  • 反模式告訴你如何採用一個很差的解決方案解決一個問題。雖然反模式看起來總像是一個好的解決方案,可是當它被真正採用後,就會帶來麻煩。
  • 反模式的工做內容包括:警告你不要陷入某種致命的誘惑;爲什麼這個解決方案從長遠看會形成不一樣的影響;建議改用其餘的模式以提供更好的解決方案。

3、結語

 折騰了快四個月的設計模式,終於到終章了~~很有收穫,時有一種豁然開朗的感受——原來繼承和組合還能這麼玩。

 好的,終於從一個設計模式的小白成長爲入門級別了,終於可以跟人吹牛逼的時候時不時說個設計模式了,哈哈哈哈...任重而道遠!

相關文章
相關標籤/搜索