目錄
六大原則
- 開閉原則(Open Close Principle)
開閉原則的意思是:對擴展開放,對修改關閉。在程序需要進行拓展的時候,不能去修改原有的代碼,實現一個熱插拔的效果。簡言之,是為了使程序的擴展性好,易於維護和升級。想要達到這樣的效果,我們需要使用接口和抽象類,后面的具體設計中我們會提到這點。
- 里氏代換原則(Liskov Substitution Principle)
里氏代換原則是面向對象設計的基本原則之一。 里氏代換原則中說,任何基類可以出現的地方,子類一定可以出現。LSP 是繼承復用的基石,只有當派生類可以替換掉基類,且軟件單位的功能不受到影響時,基類才能真正被復用,而派生類也能夠在基類的基礎上增加新的行為。里氏代換原則是對開閉原則的補充。實現開閉原則的關鍵步驟就是抽象化,而基類與子類的繼承關系就是抽象化的具體實現,所以里氏代換原則是對實現抽象化的具體步驟的規范。
- 依賴倒轉原則(Dependence Inversion Principle)
這個原則是開閉原則的基礎,具體內容:針對接口編程,依賴於抽象而不依賴於具體。
- 接口隔離原則(Interface Segregation Principle)
這個原則的意思是:使用多個隔離的接口,比使用單個接口要好。它還有另外一個意思是:降低類之間的耦合度。由此可見,其實設計模式就是從大型軟件架構出發、便於升級和維護的軟件設計思想,它強調降低依賴,降低耦合。
- 迪米特法則,又稱最少知道原則(Demeter Principle)
最少知道原則是指:一個實體應當盡量少地與其他實體之間發生相互作用,使得系統功能模塊相對獨立。
- 合成復用原則(Composite Reuse Principle)
合成復用原則是指:盡量使用合成/聚合的方式,而不是使用繼承。
創建型模式
這些設計模式提供了一種在創建對象的同時隱藏創建邏輯的方式,而不是使用 new 運算符直接實例化對象。這使得程序在判斷針對某個給定實例需要創建哪些對象時更加靈活。
工廠模式
工廠模式(Factory Pattern)是 Java 中最常用的設計模式之一。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。
在工廠模式中,我們在創建對象時不會對客戶端暴露創建邏輯,並且是通過使用一個共同的接口來指向新創建的對象。
適用場景
- 很多地方都需要創建某種對象時。
- 創建對象操作比較復雜,同時接口又需要統一時,同時又想要對外屏蔽時。
- 想要能夠方便地擴展類型實現時。
模式缺點
- 工廠對於具體實現類型會產生依賴。
- 類型非常多時工廠類會變得非常復雜。
樣例
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)模式的意義是定義一個創建產品對象的工廠接口,將實際創建工作推遲到子類當中。核心工廠類不再負責產品的創建,這樣核心類成為一個抽象工廠角色,僅負責具體工廠子類必須實現的接口,這樣進一步抽象化的好處是使得工廠方法模式可以使系統在不修改具體工廠角色的情況下引進新的產品。
工廠方法模式是簡單工廠模式的衍生,解決了許多簡單工廠模式的問題。首先完全實現‘開-閉 原則’,實現了可擴展。其次更復雜的層次結構,可以應用於產品結果復雜的場合。
適用場景
- 同“工廠方法模式”
- 不希望每次增加一個類型時都需要修改工廠基類時。
模式缺點
- 代碼結構變得更復雜了。
- 工廠也變得更多了。
樣例
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)隸屬於設計模式中的創建型模式,用於產品族的構建。抽象工廠是所有形態的工廠模式中最為抽象和最具一般性的一種形態。抽象工廠是指當有多個抽象角色時使用的一種工廠模式。抽象工廠模式可以向客戶端提供一個接口,使客戶端在不必指定產品的具體情況下,創建多個產品族中的產品對象。
工廠模式中的每一個形態都是針對一定問題的解決方案,工廠方法針對的是一類產品;而抽象工廠模式針對的是多類產品,一類產品內又有多種實現類型的情況。
適用場景
- 通常情況下產品需要成套使用。
- 每套解決方案內部又存在多種組合解決方案。
模式缺點
- 代碼結構變得更復雜了。
樣例
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 中最簡單的設計模式之一。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。
這種模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被創建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。
注意:單例類只能有一個實例。
適用場景
- 邏輯相對簡單的情況。
- 想要避免實例過多占用系統資源的情況。
模式缺點
- 修改單例對象的屬性時,需要考慮多線程和高並發場景。
樣例
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 類是獨立於其他對象的。
適用場景
- 對象內部較為復雜,同時需要分離對象的創建與構建行為時。
- 一些內部基本部件相對穩定不變,而只是其組合經常變化的時候。
- 初始化一個對象時,參數過多,或者很多參數具有默認值時。
模式缺點
- 不適合創建差異性很大的產品類。
- 如內部變化復雜,會有很多的建造類。
樣例
public interface Porudct { }
public interface Builder {
Product buildPart(Product p);
}
public interface Director {
Product getProduct();
}
原型模式
原型模式(Prototype Pattern)是用於創建重復的對象,同時又能保證性能。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。
這種模式是實現了一個原型接口,該接口用於創建當前對象的克隆。當直接創建對象的代價比較大時,則采用這種模式。例如,一個對象需要在一個高代價的數據庫操作之后被創建。我們可以緩存該對象,在下一個請求時返回它的克隆,在需要的時候更新數據庫,以此來減少數據庫調用。
適用場景
- 當一個系統應該獨立於它的產品創建,構成和表示時。
- 當要實例化的類是在運行時指定時,例如,通過動態裝載。
- 為了避免一個與產品類層次平行的工廠類層次時。
- 當一個類的實例只能有幾個不同狀態組合中的一種時。創建相應數目的原型並克隆它們可能比每次用何時的狀態手工實例化該類更方便一些。
模式缺點
- 配備克隆方法需要對類的功能進行通盤考慮,這對於全新的類不是很難,但對於已有的類不一定容易,特別當一個類引用不支持串行化的間接對象,或者引用含有循環結構的時候。
- 必須實現Cloneable接口。
樣例
public interface Cloneable {
Object clone();
}
結構型模式
適配器模式
適配器模式(Adapter Pattern)是作為兩個不兼容的接口之間的橋梁。這種類型的設計模式屬於結構型模式,它結合了兩個獨立接口的功能。這種模式涉及到一個單一的類,該類負責加入獨立的或不兼容的接口功能。
適用場景
- 可以讓任何兩個沒有關聯的類一起運行。
- 提高了類的復用。
- 增加了類的透明度。
- 靈活性好。
模式缺點
- 過多地使用適配器,會讓系統非常零亂,不易整體進行把握。
- 由於 JAVA 至多繼承一個類,所以至多只能適配一個適配者類,而且目標類必須是抽象類。
樣例
略,簡單來說就是隨意調用,類似於行為型地中介者模式。
橋接模式(稱為嫁接更直觀)
橋接(Bridge)是用於把抽象化與實現化解耦,使得二者可以獨立變化。這種類型的設計模式屬於結構型模式,它通過提供抽象化和實現化之間的橋接結構,來實現二者的解耦。
這種模式涉及到一個作為橋接的接口,使得實體類的功能獨立於接口實現類。這兩種類型的類可被結構化改變而互不影響。
我們通過下面的實例來演示橋接模式(Bridge Pattern)的用法。其中,可以使用相同的抽象類方法但是不同的橋接實現類,來畫出不同顏色的圓。
適用場景
- 想要避免在抽象與實現之間存在永久綁定。
- 如果一個系統需要在構件的抽象化角色和具體化角色之間增加更多的靈活性,避免在兩個層次之間建立靜態的繼承聯系,通過橋接模式可以使它們在抽象層建立一個關聯關系。
- 對於那些不希望使用繼承或因為多層次繼承導致系統類的個數急劇增加的系統,橋接模式尤為適用。
- 一個類存在兩個獨立變化的維度,且這兩個維度都需要進行擴展。
模式缺點
- 橋接模式的引入會增加系統的理解與設計難度,由於聚合關聯關系建立在抽象層,要求開發者針對抽象進行設計與編程。
樣例
略,簡單來說就是將多種維度的屬性從繼承關系轉化為組合關系。
過濾器模式
過濾器模式(Filter Pattern)或標准模式(Criteria Pattern)是一種設計模式,這種模式允許開發人員使用不同的標准來過濾一組對象,通過邏輯運算以解耦的方式把它們連接起來。這種類型的設計模式屬於結構型模式,它結合多個標准來獲得單一標准。
適用場景
- 設計人員將整個系統的輸入輸出行為理解為單個過濾器行為的疊加與組合。這樣可以將問題分解,化繁為簡。
- 任何兩個過濾器,只要它們之間傳送的數據遵守共同的規約就可以相連接。每個過濾器都有自己獨立的輸入輸出接口,如果過濾器間傳輸的數據遵守其規約,只要用管道將它們連接就可以正常工作。
- 整個系統易於維護和升級:舊的過濾器可以被替代,新的過濾器可以添加到已有的系統上。軟件的易於維護和升級是衡量軟件系統質量的重要指標之一。在管道-過濾器模型中,只要遵守輸入輸出數據規約,任何一個過濾器都可以被另一個新的過濾器代替,同時為增強程序功能,可以添加新的過濾器。這樣,系統的可維護性和可升級性得到了保證。
- 支持並發執行,每個過濾器作為一個單獨的執行任務,可以與其它過濾器並發執行。過濾器的執行是獨立的。不依賴於其它過濾器的。
模式缺點
- 效率較低。
- 過濾器如果組合情況復雜,那么會導致過濾器之間的結構變得復雜並且難以維護。
樣例
public interface Filter {
List<Object> filter(List<Object> list);
}
組合模式(樹型模式更貼切)
組合模式(Composite Pattern),又叫部分整體模式,是用於把一組相似的對象當作一個單一的對象。組合模式依據樹形結構來組合對象,用來表示部分以及整體層次。這種類型的設計模式屬於結構型模式,它創建了對象組的樹形結構。
這種模式創建了一個包含自己對象組的類。該類提供了修改相同對象組的方式。
適用場景
- 想表示對象的部分-整體層次結構(樹形結構)。
- 希望用戶忽略組合對象與單個對象的不同,用戶將統一地使用組合結構中的所有對象。
模式缺點
- 暫無。
樣例
public interface Node {
List<Node> getSubNodeList();
}
裝飾器模式
裝飾器模式(Decorator Pattern)允許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬於結構型模式,它是作為現有的類的一個包裝。
這種模式創建了一個裝飾類,用來包裝原有的類,並在保持類方法簽名完整性的前提下,提供了額外的功能。
適用場景
- 動態地給一個對象添加一些額外的職責,但又不想增加很多子類的情況。
- 裝飾類和被裝飾類可以獨立發展,不會相互耦合,裝飾模式是繼承的一個替代模式,裝飾模式可以動態擴展一個實現類的功能。
模式缺點
- 多層裝飾比較復雜。
樣例
public interface Shape { }
public interface ShapeDecorator {
void setShape(Shape shape);
void doSomething();
}
外觀模式
外觀模式(Facade Pattern)隱藏系統的復雜性,並向客戶端提供了一個客戶端可以訪問系統的接口。這種類型的設計模式屬於結構型模式,它向現有的系統添加一個接口,來隱藏系統的復雜性。
這種模式涉及到一個單一的類,該類提供了客戶端請求的簡化方法和對現有系統類方法的委托調用。
適用場景
- 為子系統中的一組接口提供一個一致的界面,外觀模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
模式缺點
- 不符合開閉原則,如果要改東西很麻煩,繼承重寫都不合適。
樣例
public interface Shape { }
public interface ShapeMaker {
void doSomethingComplex();
}
享元模式
享元模式(Flyweight Pattern)主要用於減少創建對象的數量,以減少內存占用和提高性能。這種類型的設計模式屬於結構型模式,它提供了減少對象數量從而改善應用所需的對象結構的方式。
享元模式嘗試重用現有的同類對象,如果未找到匹配的對象,則創建新對象。
適用場景
- 系統中有大量對象。
- 這些對象消耗大量內存。
- 這些對象的狀態大部分可以外部化。
- 這些對象可以按照內蘊狀態分為很多組,當把外蘊對象從對象中剔除出來時,每一組對象都可以用一個對象來代替。
- 系統不依賴於這些對象身份,這些對象是不可分辨的。
模式缺點
- 提高了系統的復雜度,需要分離出外部狀態和內部狀態,而且外部狀態具有固有化的性質,不應該隨着內部狀態的變化而變化,否則會造成系統的混亂。
樣例
略,簡而言之就是單例的復雜情況。
代理模式
在代理模式(Proxy Pattern)中,一個類代表另一個類的功能。這種類型的設計模式屬於結構型模式。
適用場景
- 想在訪問一個類時做一些控制。
模式缺點
- 由於在客戶端和真實主題之間增加了代理對象,因此有些類型的代理模式可能會造成請求的處理速度變慢。
- 實現代理模式需要額外的工作,有些代理模式的實現非常復雜。
樣例
略,簡單來說就是替換類型並做一些外在包裝。
行為型模式
責任鏈模式
顧名思義,責任鏈模式(Chain of Responsibility Pattern)為請求創建了一個接收者對象的鏈。這種模式給予請求的類型,對請求的發送者和接收者進行解耦。這種類型的設計模式屬於行為型模式。
在這種模式中,通常每個接收者都包含對另一個接收者的引用。如果一個對象不能處理該請求,那么它會把相同的請求傳給下一個接收者,依此類推。
適用場景
- 降低耦合度。它將請求的發送者和接收者解耦。
- 簡化了對象。使得對象不需要知道鏈的結構。
- 增強給對象指派職責的靈活性。通過改變鏈內的成員或者調動它們的次序,允許動態地新增或者刪除責任。
- 增加新的請求處理類很方便。
模式缺點
- 不能保證請求一定被接收。
- 系統性能將受到一定影響,而且在進行代碼調試時不太方便,可能會造成循環調用。
- 可能不容易觀察運行時的特征,有礙於除錯。
樣例
public interface Chain {
Chain nextChain();
void doSomething();
}
命令模式
命令模式(Command Pattern)是一種數據驅動的設計模式,它屬於行為型模式。請求以命令的形式包裹在對象中,並傳給調用對象。調用對象尋找可以處理該命令的合適的對象,並把該命令傳給相應的對象,該對象執行命令。
適用場景
- 行為請求者與行為實現者需要相互分離。
- 需要容易地添加新命令。
- 系統需要支持命令的撤銷(Undo)操作和恢復(Redo)操作時,也可以考慮使用命令模式。
模式缺點
- 使用命令模式可能會導致某些系統有過多的具體命令類。
樣例
public interface Receiver { void doAction(); }
public interface Command { void execute(); }
public interface Invoker { void execute(); }
解釋器模式
解釋器模式(Interpreter Pattern)提供了評估語言的語法或表達式的方式,它屬於行為型模式。這種模式實現了一個表達式接口,該接口解釋一個特定的上下文。這種模式被用在 SQL 解析、符號處理引擎等。
適用場景
- 可以將一個需要解釋執行的語言中的句子表示為一個抽象語法樹。
- 一些重復出現的問題可以用一種簡單的語言來進行表達。
- 一個簡單語法需要解釋的場景。
模式缺點
- 可利用場景比較少。
- 對於復雜的文法比較難維護。
- 解釋器模式會引起類膨脹。
- 解釋器模式采用遞歸調用方法。
樣例
public interface Expression { boolean interpret(String context); }
public class TerminalExpression implements Expression { …… }
public class AndExpression implements Expression { …… }
迭代器模式
迭代器模式(Iterator Pattern)是 Java 和 .Net 編程環境中非常常用的設計模式。這種模式用於順序訪問集合對象的元素,不需要知道集合對象的底層表示。
適用場景
- 訪問一個聚合對象的內容而無須暴露它的內部表示。
- 需要為聚合對象提供多種遍歷方式。
- 為遍歷不同的聚合結構提供一個統一的接口。
模式缺點
- 由於迭代器模式將存儲數據和遍歷數據的職責分離,增加新的聚合類需要對應增加新的迭代器類,類的個數成對增加,這在一定程度上增加了系統的復雜性。
樣例
public interface Iterator {
Obejct first();
boolean hasNext();
Object next();
}
public interface Aggregate { Iterator createIterator(); }
中介者模式
中介者模式(Mediator Pattern)是用來降低多個對象和類之間的通信復雜性。這種模式提供了一個中介類,該類通常處理不同類之間的通信,並支持松耦合,使代碼易於維護。中介者模式屬於行為型模式。
適用場景
- 降低了類的復雜度,將一對多轉化成了一對一。
- 各個類之間的解耦。
- 符合迪米特原則。
模式缺點
- 中介者會龐大,變得復雜難以維護。
樣例
public interface Mediator { void doAllThings(); }
備忘錄模式
備忘錄模式(Memento Pattern)保存一個對象的某個狀態,以便在適當的時候恢復對象。備忘錄模式屬於行為型模式。
適用場景
- 給用戶提供了一種可以恢復狀態的機制,可以使用戶能夠比較方便地回到某個歷史的狀態。
- 實現了信息的封裝,使得用戶不需要關心狀態的保存細節。
模式缺點
- 消耗資源。如果類的成員變量過多,勢必會占用比較大的資源,而且每一次保存都會消耗一定的內存。
樣例
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)。比如,當一個對象被修改時,則會自動通知它的依賴對象。觀察者模式屬於行為型模式。
適用場景
- 當一個抽象模型有兩個方面,其中一個方面依賴於另一方面。將這二者封裝在獨立的對象中以使它們可以各自獨立地改變和復用。
- 當對一個對象的改變需要同時(通知)改變其他對象,而不知道具體有多少對象需要被改變。
- 當一個對象必須通知其他對象,而它又不能假定其他對象是誰。換言之,不希望這些對象是緊密耦合的。
模式缺點
- 如果一個被觀察者對象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間。
- 如果在觀察者和觀察目標之間有循環依賴的話,觀察目標會觸發它們之間進行循環調用,可能導致系統崩潰。
- 觀察者模式沒有相應的機制讓觀察者知道所觀察的目標對象是怎么發生變化的,而僅僅只是知道觀察目標發生了變化。
樣例
public interface Observer {
void update();
}
public interface Subject {
void attach(Observer o)
void detach(Observer o);
void notify();
}
狀態模式(或者叫發布-訂閱模式)
在狀態模式(State Pattern)中,類的行為是基於它的狀態改變的。這種類型的設計模式屬於行為型模式。在狀態模式中,我們創建表示各種狀態的對象和一個行為隨着狀態對象改變而改變的 context 對象。
適用場景
- 行為隨狀態改變而改變的場景。
- 條件、分支語句的代替者。
模式缺點
- 狀態模式的使用必然會增加系統類和對象的個數。
- 狀態模式的結構與實現都較為復雜,如果使用不當將導致程序結構和代碼的混亂。
- 狀態模式對"開閉原則"的支持並不太好,對於可以切換狀態的狀態模式,增加新的狀態類需要修改那些負責狀態轉換的源代碼,否則無法切換到新增狀態,而且修改某個狀態類的行為也需修改對應類的源代碼。
樣例
public interface State {
void handle();
}
public interface Context {
void setState(State s);
State getState();
}
空對象模式
有兩種含義:
- 在空對象模式(Null Object Pattern)中,一個空對象取代 NULL 對象實例的檢查。
- Null 對象不是檢查空值,而是反應一個不做任何動作的關系,這樣的 Null 對象也可以在數據不可用的時候提供默認的行為。
在空對象模式中,我們創建一個指定各種要執行的操作的抽象類和擴展該類的實體類,還創建一個未對該類做任何實現的空對象類,該空對象類將無縫地使用在需要檢查空值的地方。
適用場景
- 想要避免使用空指針(或null對象)的情況。
- 想要默認情況下具有“不做任何操作”的行為的情況。
模式缺點
- 必須手動實現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 對象的執行算法。
適用場景
- 如果在一個系統里面有許多類,它們之間的區別僅在於它們的行為,那么使用策略模式可以動態地讓一個對象在許多行為中選擇一種行為。
- 一個系統需要動態地在幾種算法中選擇一種。
- 如果一個對象有很多的行為,如果不用恰當的模式,這些行為就只好使用多重的條件選擇語句來實現。
模式缺點
- 策略類會增多。
- 所有策略類都需要對外暴露。
樣例
public interface Strategy {
void strategy();
}
模板模式
在模板模式(Template Pattern)中,一個抽象類公開定義了執行它的方法的方式/模板。它的子類可以按需要重寫方法實現,但調用將以抽象類中定義的方式進行。這種類型的設計模式屬於行為型模式。
適用場景
- 有多個子類共有的方法,且邏輯相同。
- 重要的、復雜的方法,可以考慮作為模板方法。
模式缺點
- 每一個不同的實現都需要一個子類來實現,導致類的個數增加,使得系統更加龐大。
樣例
略,其實繼承情況下,就是對某些方法提供默認實現,對某些方法允許重寫覆蓋。
訪問者模式
在訪問者模式(Visitor Pattern)中,我們使用了一個訪問者類,它改變了元素類的執行算法。通過這種方式,元素的執行算法可以隨着訪問者改變而改變。這種類型的設計模式屬於行為型模式。根據模式,元素對象已接受訪問者對象,這樣訪問者對象就可以處理元素對象上的操作。
適用場景
- 對象結構中對象對應的類很少改變,但經常需要在此對象結構上定義新的操作。
- 需要對一個對象結構中的對象進行很多不同的並且不相關的操作,而需要避免讓這些操作"污染"這些對象的類,也不希望在增加新操作時修改這些類。
模式缺點
- 具體元素對訪問者公布細節,違反了迪米特原則。
- 具體元素變更比較困難。
- 違反了依賴倒置原則,依賴了具體類,沒有依賴抽象。
樣例
public interface Visitor {
void visit(Element e);
}
public interface Element {
void accept(Visitor v);
}
// 通常在accept中,調用v.visit(this)來進行訪問操作。
