關於27種常見設計模式的總結

目錄

六大原則

  1. 開閉原則(Open Close Principle)

開閉原則的意思是:對擴展開放,對修改關閉。在程序須要進行拓展的時候,不能去修改原有的代碼,實現一個熱插拔的效果。簡言之,是爲了使程序的擴展性好,易於維護和升級。想要達到這樣的效果,咱們須要使用接口和抽象類,後面的具體設計中咱們會提到這點。java

  1. 里氏代換原則(Liskov Substitution Principle)

里氏代換原則是面向對象設計的基本原則之一。 里氏代換原則中說,任何基類能夠出現的地方,子類必定能夠出現。LSP 是繼承複用的基石,只有當派生類能夠替換掉基類,且軟件單位的功能不受到影響時,基類才能真正被複用,而派生類也可以在基類的基礎上增長新的行爲。里氏代換原則是對開閉原則的補充。實現開閉原則的關鍵步驟就是抽象化,而基類與子類的繼承關係就是抽象化的具體實現,因此里氏代換原則是對實現抽象化的具體步驟的規範。算法

  1. 依賴倒轉原則(Dependence Inversion Principle)

這個原則是開閉原則的基礎,具體內容:針對接口編程,依賴於抽象而不依賴於具體。數據庫

  1. 接口隔離原則(Interface Segregation Principle)

這個原則的意思是:使用多個隔離的接口,比使用單個接口要好。它還有另一個意思是:下降類之間的耦合度。因而可知,其實設計模式就是從大型軟件架構出發、便於升級和維護的軟件設計思想,它強調下降依賴,下降耦合。編程

  1. 迪米特法則,又稱最少知道原則(Demeter Principle)

最少知道原則是指:一個實體應當儘可能少地與其餘實體之間發生相互做用,使得系統功能模塊相對獨立。設計模式

  1. 合成複用原則(Composite Reuse Principle)

合成複用原則是指:儘可能使用合成/聚合的方式,而不是使用繼承。緩存

建立型模式

這些設計模式提供了一種在建立對象的同時隱藏建立邏輯的方式,而不是使用 new 運算符直接實例化對象。這使得程序在判斷針對某個給定實例須要建立哪些對象時更加靈活。多線程

工廠模式

工廠模式(Factory Pattern)是 Java 中最經常使用的設計模式之一。這種類型的設計模式屬於建立型模式,它提供了一種建立對象的最佳方式。架構

在工廠模式中,咱們在建立對象時不會對客戶端暴露建立邏輯,而且是經過使用一個共同的接口來指向新建立的對象。併發

適用場景

  1. 不少地方都須要建立某種對象時。
  2. 建立對象操做比較複雜,同時接口又須要統一時,同時又想要對外屏蔽時。
  3. 想要可以方便地擴展類型實現時。

模式缺點

  1. 工廠對於具體實現類型會產生依賴。
  2. 類型很是多時工廠類會變得很是複雜。

樣例

public interface Shape {}
public class Circle implements Shape {}
public class Square implements Shape {}
public class ShapeFactory {
    public Shape getShape1() { return new Circle(); }
    public Shape getShape2() { return new Square(); }
    public Shape getShape(String shape) {
        switch (shape) {
            case "circle": return new Circle();
            case "square": return new Square();
        }
        return null;
    }
}

工廠方法模式

工廠方法(Factory Method)模式的意義是定義一個建立產品對象的工廠接口,將實際建立工做推遲到子類當中。核心工廠類再也不負責產品的建立,這樣核心類成爲一個抽象工廠角色,僅負責具體工廠子類必須實現的接口,這樣進一步抽象化的好處是使得工廠方法模式可使系統在不修改具體工廠角色的狀況下引進新的產品。高併發

工廠方法模式是簡單工廠模式的衍生,解決了許多簡單工廠模式的問題。首先徹底實現‘開-閉 原則’,實現了可擴展。其次更復雜的層次結構,能夠應用於產品結果複雜的場合。

適用場景

  1. 同「工廠方法模式」
  2. 不但願每次增長一個類型時都須要修改工廠基類時。

模式缺點

  1. 代碼結構變得更復雜了。
  2. 工廠也變得更多了。

樣例

public interface Shape {}
public class Circle implements Shape {}
public class Square implements Shape {}
public interface ShapeAbstractFactory {
    Shape getShape();
}
public class CircleFactory implements ShapeAbstractFactory {
    public Shape getShape() { return new Circle(); }
}
public class SquareFactory implements ShapeAbstractFactory {
    public Shape getShape() { return new Square(); }
}

抽象工廠方法模式

抽象工廠模式(Abstract Factory Pattern)隸屬於設計模式中的建立型模式,用於產品族的構建。抽象工廠是全部形態的工廠模式中最爲抽象和最具通常性的一種形態。抽象工廠是指當有多個抽象角色時使用的一種工廠模式。抽象工廠模式能夠向客戶端提供一個接口,使客戶端在沒必要指定產品的具體狀況下,建立多個產品族中的產品對象。

工廠模式中的每個形態都是針對必定問題的解決方案,工廠方法針對的是一類產品;而抽象工廠模式針對的是多類產品,一類產品內又有多種實現類型的狀況。

適用場景

  1. 一般狀況下產品須要成套使用。
  2. 每套解決方案內部又存在多種組合解決方案。

模式缺點

  1. 代碼結構變得更復雜了。

樣例

public interface Shape {}
public class Circle implements Shape {}
public class Square implements Shape {}
public interface color {}
public class Red implements Color {}
public class Blue implements Color {}
public interface AbstractFactory {
    Shape getShape();
    Red getColor();
}
public class Factory1 implements AbstractFactory { ... }
public class Factory2 implements AbstractFactory { ... }

單例模式

單例模式(Singleton Pattern)是 Java 中最簡單的設計模式之一。這種類型的設計模式屬於建立型模式,它提供了一種建立對象的最佳方式。

這種模式涉及到一個單一的類,該類負責建立本身的對象,同時確保只有單個對象被建立。這個類提供了一種訪問其惟一的對象的方式,能夠直接訪問,不須要實例化該類的對象。

注意:單例類只能有一個實例。

適用場景

  1. 邏輯相對簡單的狀況。
  2. 想要避免實例過多佔用系統資源的狀況。

模式缺點

  1. 修改單例對象的屬性時,須要考慮多線程和高併發場景。

樣例

public class Singleton {
    private volatile static Singleton singleton;
    private Singleton (){}  // 不容許經過new來實例化對象
    public static Singleton getSingleton() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

建造者模式

建造者模式(Builder Pattern)使用多個簡單的對象一步一步構建成一個複雜的對象。這種類型的設計模式屬於建立型模式,它提供了一種建立對象的最佳方式。

一個 Builder 類會一步一步構造最終的對象。該 Builder 類是獨立於其餘對象的。

適用場景

  1. 對象內部較爲複雜,同時須要分離對象的建立與構建行爲時。
  2. 一些內部基本部件相對穩定不變,而只是其組合常常變化的時候。
  3. 初始化一個對象時,參數過多,或者不少參數具備默認值時。

模式缺點

  1. 不適合建立差別性很大的產品類。
  2. 如內部變化複雜,會有不少的建造類。

樣例

public interface Porudct { }
public interface Builder {
    Product buildPart(Product p);
}
public interface Director {
    Product getProduct();
}

原型模式

原型模式(Prototype Pattern)是用於建立重複的對象,同時又能保證性能。這種類型的設計模式屬於建立型模式,它提供了一種建立對象的最佳方式。

這種模式是實現了一個原型接口,該接口用於建立當前對象的克隆。當直接建立對象的代價比較大時,則採用這種模式。例如,一個對象須要在一個高代價的數據庫操做以後被建立。咱們能夠緩存該對象,在下一個請求時返回它的克隆,在須要的時候更新數據庫,以此來減小數據庫調用。

適用場景

  1. 當一個系統應該獨立於它的產品建立,構成和表示時。
  2. 當要實例化的類是在運行時指定時,例如,經過動態裝載。
  3. 爲了不一個與產品類層次平行的工廠類層次時。
  4. 當一個類的實例只能有幾個不一樣狀態組合中的一種時。建立相應數目的原型並克隆它們可能比每次用什麼時候的狀態手工實例化該類更方便一些。

模式缺點

  1. 配備克隆方法須要對類的功能進行通盤考慮,這對於全新的類不是很難,但對於已有的類不必定容易,特別當一個類引用不支持串行化的間接對象,或者引用含有循環結構的時候。
  2. 必須實現Cloneable接口。

樣例

public interface Cloneable {
    Object clone();
}

結構型模式

適配器模式

適配器模式(Adapter Pattern)是做爲兩個不兼容的接口之間的橋樑。這種類型的設計模式屬於結構型模式,它結合了兩個獨立接口的功能。這種模式涉及到一個單一的類,該類負責加入獨立的或不兼容的接口功能。

適用場景

  1. 可讓任何兩個沒有關聯的類一塊兒運行。
  2. 提升了類的複用。
  3. 增長了類的透明度。
  4. 靈活性好。

模式缺點

  1. 過多地使用適配器,會讓系統很是零亂,不易總體進行把握。
  2. 因爲 JAVA 至多繼承一個類,因此至多隻能適配一個適配者類,並且目標類必須是抽象類。

樣例

略,簡單來講就是隨意調用,相似於行爲型地中介者模式。

橋接模式(稱爲嫁接更直觀)

橋接(Bridge)是用於把抽象化與實現化解耦,使得兩者能夠獨立變化。這種類型的設計模式屬於結構型模式,它經過提供抽象化和實現化之間的橋接結構,來實現兩者的解耦。

這種模式涉及到一個做爲橋接的接口,使得實體類的功能獨立於接口實現類。這兩種類型的類可被結構化改變而互不影響。

咱們經過下面的實例來演示橋接模式(Bridge Pattern)的用法。其中,可使用相同的抽象類方法可是不一樣的橋接實現類,來畫出不一樣顏色的圓。

適用場景

  1. 想要避免在抽象與實現之間存在永久綁定。
  2. 若是一個系統須要在構件的抽象化角色和具體化角色之間增長更多的靈活性,避免在兩個層次之間創建靜態的繼承聯繫,經過橋接模式可使它們在抽象層創建一個關聯關係。
  3. 對於那些不但願使用繼承或由於多層次繼承致使系統類的個數急劇增長的系統,橋接模式尤其適用。
  4. 一個類存在兩個獨立變化的維度,且這兩個維度都須要進行擴展。

模式缺點

  1. 橋接模式的引入會增長系統的理解與設計難度,因爲聚合關聯關係創建在抽象層,要求開發者針對抽象進行設計與編程。

樣例

略,簡單來講就是將多種維度的屬性從繼承關係轉化爲組合關係。

過濾器模式

過濾器模式(Filter Pattern)或標準模式(Criteria Pattern)是一種設計模式,這種模式容許開發人員使用不一樣的標準來過濾一組對象,經過邏輯運算以解耦的方式把它們鏈接起來。這種類型的設計模式屬於結構型模式,它結合多個標準來得到單一標準。

適用場景

  1. 設計人員將整個系統的輸入輸出行爲理解爲單個過濾器行爲的疊加與組合。這樣能夠將問題分解,化繁爲簡。
  2. 任何兩個過濾器,只要它們之間傳送的數據遵照共同的規約就能夠相鏈接。每一個過濾器都有本身獨立的輸入輸出接口,若是過濾器間傳輸的數據遵照其規約,只要用管道將它們鏈接就能夠正常工做。
  3. 整個系統易於維護和升級:舊的過濾器能夠被替代,新的過濾器能夠添加到已有的系統上。軟件的易於維護和升級是衡量軟件系統質量的重要指標之一。在管道-過濾器模型中,只要遵照輸入輸出數據規約,任何一個過濾器均可以被另外一個新的過濾器代替,同時爲加強程序功能,能夠添加新的過濾器。這樣,系統的可維護性和可升級性獲得了保證。
  4. 支持併發執行,每一個過濾器做爲一個單獨的執行任務,能夠與其它過濾器併發執行。過濾器的執行是獨立的。不依賴於其它過濾器的。

模式缺點

  1. 效率較低。
  2. 過濾器若是組合狀況複雜,那麼會致使過濾器之間的結構變得複雜而且難以維護。

樣例

public interface Filter {
    List<Object> filter(List<Object> list);
}

組合模式(樹型模式更貼切)

組合模式(Composite Pattern),又叫部分總體模式,是用於把一組類似的對象看成一個單一的對象。組合模式依據樹形結構來組合對象,用來表示部分以及總體層次。這種類型的設計模式屬於結構型模式,它建立了對象組的樹形結構。

這種模式建立了一個包含本身對象組的類。該類提供了修改相同對象組的方式。

適用場景

  1. 想表示對象的部分-總體層次結構(樹形結構)。
  2. 但願用戶忽略組合對象與單個對象的不一樣,用戶將統一地使用組合結構中的全部對象。

模式缺點

  1. 暫無。

樣例

public interface Node {
    List<Node> getSubNodeList();
}

裝飾器模式

裝飾器模式(Decorator Pattern)容許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬於結構型模式,它是做爲現有的類的一個包裝。

這種模式建立了一個裝飾類,用來包裝原有的類,並在保持類方法簽名完整性的前提下,提供了額外的功能。

適用場景

  1. 動態地給一個對象添加一些額外的職責,但又不想增長不少子類的狀況。
  2. 裝飾類和被裝飾類能夠獨立發展,不會相互耦合,裝飾模式是繼承的一個替代模式,裝飾模式能夠動態擴展一個實現類的功能。

模式缺點

  1. 多層裝飾比較複雜。

樣例

public interface Shape { }
public interface ShapeDecorator {
    void setShape(Shape shape);
    void doSomething();
}

外觀模式

外觀模式(Facade Pattern)隱藏系統的複雜性,並向客戶端提供了一個客戶端能夠訪問系統的接口。這種類型的設計模式屬於結構型模式,它向現有的系統添加一個接口,來隱藏系統的複雜性。

這種模式涉及到一個單一的類,該類提供了客戶端請求的簡化方法和對現有系統類方法的委託調用。

適用場景

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

模式缺點

  1. 不符合開閉原則,若是要改東西很麻煩,繼承重寫都不合適。

樣例

public interface Shape { }
public interface ShapeMaker {
    void doSomethingComplex();
}

享元模式

享元模式(Flyweight Pattern)主要用於減小建立對象的數量,以減小內存佔用和提升性能。這種類型的設計模式屬於結構型模式,它提供了減小對象數量從而改善應用所需的對象結構的方式。

享元模式嘗試重用現有的同類對象,若是未找到匹配的對象,則建立新對象。

適用場景

  1. 系統中有大量對象。
  2. 這些對象消耗大量內存。
  3. 這些對象的狀態大部分能夠外部化。
  4. 這些對象能夠按照內蘊狀態分爲不少組,當把外蘊對象從對象中剔除出來時,每一組對象均可以用一個對象來代替。
  5. 系統不依賴於這些對象身份,這些對象是不可分辨的。

模式缺點

  1. 提升了系統的複雜度,須要分離出外部狀態和內部狀態,並且外部狀態具備固有化的性質,不該該隨着內部狀態的變化而變化,不然會形成系統的混亂。

樣例

略,簡而言之就是單例的複雜狀況。

代理模式

在代理模式(Proxy Pattern)中,一個類表明另外一個類的功能。這種類型的設計模式屬於結構型模式。

適用場景

  1. 想在訪問一個類時作一些控制。

模式缺點

  1. 因爲在客戶端和真實主題之間增長了代理對象,所以有些類型的代理模式可能會形成請求的處理速度變慢。
  2. 實現代理模式須要額外的工做,有些代理模式的實現很是複雜。

樣例

略,簡單來講就是替換類型並作一些外在包裝。

行爲型模式

責任鏈模式

顧名思義,責任鏈模式(Chain of Responsibility Pattern)爲請求建立了一個接收者對象的鏈。這種模式給予請求的類型,對請求的發送者和接收者進行解耦。這種類型的設計模式屬於行爲型模式。

在這種模式中,一般每一個接收者都包含對另外一個接收者的引用。若是一個對象不能處理該請求,那麼它會把相同的請求傳給下一個接收者,依此類推。

適用場景

  1. 下降耦合度。它將請求的發送者和接收者解耦。
  2. 簡化了對象。使得對象不須要知道鏈的結構。
  3. 加強給對象指派職責的靈活性。經過改變鏈內的成員或者調動它們的次序,容許動態地新增或者刪除責任。
  4. 增長新的請求處理類很方便。

模式缺點

  1. 不能保證請求必定被接收。
  2. 系統性能將受到必定影響,並且在進行代碼調試時不太方便,可能會形成循環調用。
  3. 可能不容易觀察運行時的特徵,有礙於除錯。

樣例

public interface Chain {
    Chain nextChain();
    void doSomething();
}

命令模式

命令模式(Command Pattern)是一種數據驅動的設計模式,它屬於行爲型模式。請求以命令的形式包裹在對象中,並傳給調用對象。調用對象尋找能夠處理該命令的合適的對象,並把該命令傳給相應的對象,該對象執行命令。

適用場景

  1. 行爲請求者與行爲實現者須要相互分離。
  2. 須要容易地添加新命令。
  3. 系統須要支持命令的撤銷(Undo)操做和恢復(Redo)操做時,也能夠考慮使用命令模式。

模式缺點

  1. 使用命令模式可能會致使某些系統有過多的具體命令類。

樣例

public interface Receiver { void doAction(); }
public interface Command { void execute(); }
public interface Invoker { void execute(); }

解釋器模式

解釋器模式(Interpreter Pattern)提供了評估語言的語法或表達式的方式,它屬於行爲型模式。這種模式實現了一個表達式接口,該接口解釋一個特定的上下文。這種模式被用在 SQL 解析、符號處理引擎等。

適用場景

  1. 能夠將一個須要解釋執行的語言中的句子表示爲一個抽象語法樹。
  2. 一些重複出現的問題能夠用一種簡單的語言來進行表達。
  3. 一個簡單語法須要解釋的場景。

模式缺點

  1. 可利用場景比較少。
  2. 對於複雜的文法比較難維護。
  3. 解釋器模式會引發類膨脹。
  4. 解釋器模式採用遞歸調用方法。

樣例

public interface Expression { boolean interpret(String context); }
public class TerminalExpression implements Expression { …… }
public class AndExpression implements Expression { …… }

迭代器模式

迭代器模式(Iterator Pattern)是 Java 和 .Net 編程環境中很是經常使用的設計模式。這種模式用於順序訪問集合對象的元素,不須要知道集合對象的底層表示。

適用場景

  1. 訪問一個聚合對象的內容而無須暴露它的內部表示。
  2. 須要爲聚合對象提供多種遍歷方式。
  3. 爲遍歷不一樣的聚合結構提供一個統一的接口。

模式缺點

  1. 因爲迭代器模式將存儲數據和遍歷數據的職責分離,增長新的聚合類須要對應增長新的迭代器類,類的個數成對增長,這在必定程度上增長了系統的複雜性。

樣例

public interface Iterator {
    Obejct first();
    boolean hasNext();
    Object next();
}
public interface Aggregate { Iterator createIterator(); }

中介者模式

中介者模式(Mediator Pattern)是用來下降多個對象和類之間的通訊複雜性。這種模式提供了一箇中介類,該類一般處理不一樣類之間的通訊,並支持鬆耦合,使代碼易於維護。中介者模式屬於行爲型模式。

適用場景

  1. 下降了類的複雜度,將一對多轉化成了一對一。
  2. 各個類之間的解耦。
  3. 符合迪米特原則。

模式缺點

  1. 中介者會龐大,變得複雜難以維護。

樣例

public interface Mediator { void doAllThings(); }

備忘錄模式

備忘錄模式(Memento Pattern)保存一個對象的某個狀態,以便在適當的時候恢復對象。備忘錄模式屬於行爲型模式。

適用場景

  1. 給用戶提供了一種能夠恢復狀態的機制,可使用戶可以比較方便地回到某個歷史的狀態。
  2. 實現了信息的封裝,使得用戶不須要關心狀態的保存細節。

模式缺點

  1. 消耗資源。若是類的成員變量過多,勢必會佔用比較大的資源,並且每一次保存都會消耗必定的內存。

樣例

public interface Memento {
    void setState(int state);
    int getState();
}
public interface Originator {
    void restore(Memento memento);
    Memento createMemento();
}
public interface Caretaker {
    Memento getMemento(int i);
    void addMemento(Memento memento);
}

觀察者模式(或者叫發佈-訂閱模式)

當對象間存在一對多關係時,則使用觀察者模式(Observer Pattern)。好比,當一個對象被修改時,則會自動通知它的依賴對象。觀察者模式屬於行爲型模式。

適用場景

  1. 當一個抽象模型有兩個方面,其中一個方面依賴於另外一方面。將這兩者封裝在獨立的對象中以使它們能夠各自獨立地改變和複用。
  2. 當對一個對象的改變須要同時(通知)改變其餘對象,而不知道具體有多少對象須要被改變。
  3. 當一個對象必須通知其餘對象,而它又不能假定其餘對象是誰。換言之,不但願這些對象是緊密耦合的。

模式缺點

  1. 若是一個被觀察者對象有不少的直接和間接的觀察者的話,將全部的觀察者都通知到會花費不少時間。
  2. 若是在觀察者和觀察目標之間有循環依賴的話,觀察目標會觸發它們之間進行循環調用,可能致使系統崩潰。
  3. 觀察者模式沒有相應的機制讓觀察者知道所觀察的目標對象是怎麼發生變化的,而僅僅只是知道觀察目標發生了變化。

樣例

public interface Observer {
    void update();
}
public interface Subject {
    void attach(Observer o)
    void detach(Observer o);
    void notify();
}

狀態模式(或者叫發佈-訂閱模式)

在狀態模式(State Pattern)中,類的行爲是基於它的狀態改變的。這種類型的設計模式屬於行爲型模式。在狀態模式中,咱們建立表示各類狀態的對象和一個行爲隨着狀態對象改變而改變的 context 對象。

適用場景

  1. 行爲隨狀態改變而改變的場景。
  2. 條件、分支語句的代替者。

模式缺點

  1. 狀態模式的使用必然會增長系統類和對象的個數。
  2. 狀態模式的結構與實現都較爲複雜,若是使用不當將致使程序結構和代碼的混亂。
  3. 狀態模式對"開閉原則"的支持並不太好,對於能夠切換狀態的狀態模式,增長新的狀態類須要修改那些負責狀態轉換的源代碼,不然沒法切換到新增狀態,並且修改某個狀態類的行爲也需修改對應類的源代碼。

樣例

public interface State {
   void handle();
}
public interface Context {
    void setState(State s);
    State getState();
}

空對象模式

有兩種含義:

  1. 在空對象模式(Null Object Pattern)中,一個空對象取代 NULL 對象實例的檢查。
  2. Null 對象不是檢查空值,而是反應一個不作任何動做的關係,這樣的 Null 對象也能夠在數據不可用的時候提供默認的行爲。

在空對象模式中,咱們建立一個指定各類要執行的操做的抽象類和擴展該類的實體類,還建立一個未對該類作任何實現的空對象類,該空對象類將無縫地使用在須要檢查空值的地方。

適用場景

  1. 想要避免使用空指針(或null對象)的狀況。
  2. 想要默認狀況下具備「不作任何操做」的行爲的狀況。

模式缺點

  1. 必須手動實現isNil方法(或isNull方法)。

樣例

// 含義1:取代null的檢查
public interface Nullable {
   boolean isNull();
}

// 含義2:不作任何動做的關係
public interface Command {
    void handle();
}
public class NullCommand implements Command {
    public void handle() {
        return;
    }
}

策略模式

在策略模式(Strategy Pattern)中,一個類的行爲或其算法能夠在運行時更改。這種類型的設計模式屬於行爲型模式。

在策略模式中,咱們建立表示各類策略的對象和一個行爲隨着策略對象改變而改變的 context 對象。策略對象改變 context 對象的執行算法。

適用場景

  1. 若是在一個系統裏面有許多類,它們之間的區別僅在於它們的行爲,那麼使用策略模式能夠動態地讓一個對象在許多行爲中選擇一種行爲。
  2. 一個系統須要動態地在幾種算法中選擇一種。
  3. 若是一個對象有不少的行爲,若是不用恰當的模式,這些行爲就只好使用多重的條件選擇語句來實現。

模式缺點

  1. 策略類會增多。
  2. 全部策略類都須要對外暴露。

樣例

public interface Strategy {
   void strategy();
}

模板模式

在模板模式(Template Pattern)中,一個抽象類公開定義了執行它的方法的方式/模板。它的子類能夠按須要重寫方法實現,但調用將以抽象類中定義的方式進行。這種類型的設計模式屬於行爲型模式。

適用場景

  1. 有多個子類共有的方法,且邏輯相同。
  2. 重要的、複雜的方法,能夠考慮做爲模板方法。

模式缺點

  1. 每個不一樣的實現都須要一個子類來實現,致使類的個數增長,使得系統更加龐大。

樣例

略,其實繼承狀況下,就是對某些方法提供默認實現,對某些方法容許重寫覆蓋。

訪問者模式

在訪問者模式(Visitor Pattern)中,咱們使用了一個訪問者類,它改變了元素類的執行算法。經過這種方式,元素的執行算法能夠隨着訪問者改變而改變。這種類型的設計模式屬於行爲型模式。根據模式,元素對象已接受訪問者對象,這樣訪問者對象就能夠處理元素對象上的操做。

適用場景

  1. 對象結構中對象對應的類不多改變,但常常須要在此對象結構上定義新的操做。
  2. 須要對一個對象結構中的對象進行不少不一樣的而且不相關的操做,而須要避免讓這些操做"污染"這些對象的類,也不但願在增長新操做時修改這些類。

模式缺點

  1. 具體元素對訪問者公佈細節,違反了迪米特原則。
  2. 具體元素變動比較困難。
  3. 違反了依賴倒置原則,依賴了具體類,沒有依賴抽象。

樣例

public interface Visitor {
   void visit(Element e);
}
public interface Element {
   void accept(Visitor v);
}
// 一般在accept中,調用v.visit(this)來進行訪問操做。
相關文章
相關標籤/搜索