結構型模式
代理模式(Proxy Pattern)
代理模式(Proxy Pattern)是一種結構型設計模式,它通過引入一個代理對象來控制對另一個對象的訪問。這個代理對象可以為被代理的對象提供額外的功能,例如訪問控制、延遲初始化、日志記錄、或網絡訪問等。
適用場景
-
遠程代理:
- 為一個對象在不同的地址空間提供局部代表。
-
虛擬代理:
- 根據需要創建開銷很大的對象。
-
保護代理:
- 控制對原始對象的訪問。
-
智能指引:
- 在訪問對象時執行一些附加操作,例如計數操作或引用檢測。
實現示例(Java)
以下是一個簡單的代理模式的實現示例,展示如何通過代理對象控制對實際對象的訪問。
1. 定義主題接口
public interface Subject {void request();
}
- 說明:
Subject
接口定義了一個request
方法,這是實際對象和代理對象都需要實現的方法。
2. 定義真實主題類(RealSubject)
public class RealSubject implements Subject {public void request() {System.out.println("RealSubject: Handling request.");}
}
- 說明:
RealSubject
類實現了Subject
接口的request
方法,表示真實處理請求的類。
3. 定義代理類(Proxy)
public class Proxy implements Subject {private RealSubject realSubject;public Proxy(RealSubject realSubject) {this.realSubject = realSubject;}public void request() {if (this.checkAccess()) {this.realSubject.request();this.logAccess();}}private boolean checkAccess() {// 檢查訪問權限System.out.println("Proxy: Checking access prior to firing a real request.");return true;}private void logAccess() {// 記錄請求日志System.out.println("Proxy: Logging the time of request.");}
}
- 說明:
Proxy
類實現了Subject
接口,并持有一個RealSubject
對象。- 在
request
方法中,代理類先檢查訪問權限,再調用真實對象的request
方法,最后記錄請求日志。
4. 客戶端代碼
public class Client {public static void main(String[] args) {RealSubject realSubject = new RealSubject();Proxy proxy = new Proxy(realSubject);proxy.request();}
}
- 說明:
Client
類創建了RealSubject
和Proxy
對象,通過Proxy
對象調用request
方法,從而控制對RealSubject
的訪問。
優點
-
隔離性:
- 代理模式可以作為調用者和實際對象之間的中介,降低系統組件之間的耦合度,增強對象間的隔離性。
-
安全性:
- 通過代理可以控制對實際對象的訪問,實現安全檢查以及深度驗證。
-
擴展性:
- 代理模式在不修改具體對象代碼的情況下,可以靈活地增加功能。
-
智能化:
- 可以在不改變服務對象接口的前提下,實施一些附加操作,如延遲初始化和訪問日志等。
缺點
-
代碼復雜性:
- 引入代理也意味著增加了系統的復雜性,可能會引入新的類和接口,增加了代碼的理解和維護成本。
-
響應時間:
- 代理模式可能會導致系統運行速度減慢,特別是在代理操作中加入了大量處理邏輯時。
-
設計難度:
- 正確地設計和實施代理模式需要仔細考慮整個系統的設計,以確保不會對系統性能產生負面影響。
類圖
Client|v
Subject <---- Proxy <---- RealSubject
總結
代理模式提供了一種有效的方式來控制和管理對象的訪問。通過使用代理,可以在保持業務對象職責清晰的同時,增加各種功能。此模式特別適用于需要對業務對象進行訪問控制和其他預處理操作的場景。
外觀模式(Facade Pattern)
外觀模式(Facade Pattern)是一種結構型設計模式,它通過提供一個統一的接口,用來訪問子系統中的一群接口,從而讓復雜子系統更容易使用。外觀模式定義了一個高層接口,使得這一子系統更加容易使用。
適用場景
-
簡化復雜系統的接口:
- 為復雜的子系統提供一個簡單的接口,減少外部與子系統的交互復雜度。
-
層次結構:
- 在多層系統結構中,可以使用外觀模式定義每層的入口,簡化層之間的依賴關系。
-
解耦系統:
- 通過引入外觀模式,使得子系統與客戶端之間的耦合度降低。
實現示例(Java)
以下是一個簡單的外觀模式的實現示例,展示如何通過外觀類簡化對子系統的使用。
1. 定義子系統類
public class SubsystemA {public void operationA() {System.out.println("SubsystemA: operationA");}
}public class SubsystemB {public void operationB() {System.out.println("SubsystemB: operationB");}
}public class SubsystemC {public void operationC() {System.out.println("SubsystemC: operationC");}
}
2. 定義外觀類
public class Facade {private SubsystemA subsystemA;private SubsystemB subsystemB;private SubsystemC subsystemC;public Facade() {this.subsystemA = new SubsystemA();this.subsystemB = new SubsystemB();this.subsystemC = new SubsystemC();}public void operation1() {System.out.println("Facade: operation1");subsystemA.operationA();subsystemB.operationB();}public void operation2() {System.out.println("Facade: operation2");subsystemB.operationB();subsystemC.operationC();}
}
3. 客戶端代碼
public class Client {public static void main(String[] args) {Facade facade = new Facade();facade.operation1();facade.operation2();}
}
注釋說明
-
子系統類:
SubsystemA
,SubsystemB
, 和SubsystemC
是子系統的具體實現類,每個類都有自己獨特的操作方法。
-
外觀類:
Facade
類持有子系統的對象,并提供簡化的接口operation1
和operation2
來調用子系統的功能。
-
客戶端代碼:
Client
類通過Facade
類來調用operation1
和operation2
,從而簡化了對復雜子系統的使用。
優點
-
簡化接口:
- 外觀模式為子系統提供了一個簡單的接口,減少了與子系統交互的復雜度。
-
松散耦合:
- 外觀模式使得子系統與客戶端之間的耦合度降低,有助于提高系統的可維護性和擴展性。
-
更好的分層:
- 外觀模式有助于建立一個清晰的分層結構,定義每層的入口。
缺點
-
不符合開閉原則:
- 增加新的子系統功能時,可能需要修改外觀類,違背了開閉原則(對擴展開放,對修改關閉)。
-
可能造成性能問題:
- 在某些情況下,使用外觀模式可能會導致系統性能下降,因為所有請求都需要經過外觀類。
類圖
Client|v
Facade ----> SubsystemA----> SubsystemB----> SubsystemC
總結
外觀模式通過提供一個簡化的接口,使得復雜子系統的使用變得更加容易。它適用于需要簡化子系統接口、減少客戶端與子系統直接交互、解耦系統層次結構的場景。盡管它有可能違反開閉原則,但在大多數情況下,它的優點遠遠超過其缺點,使得系統設計更加清晰和易于維護。