代理模式
在代理模式(Proxy Pattern)中,一個類代表另一個類的功能,這種類型的設計模式屬于結構型模式。
代理模式通過引入一個代理對象來控制對原對象的訪問。代理對象在客戶端和目標對象之間充當中介,負責將客戶端的請求轉發給目標對象,同時可以在轉發請求前后進行額外的處理。
在代理模式中,我們創建具有現有對象的對象,以便向外界提供功能接口。
介紹
意圖
為其他對象提供一種代理以控制對這個對象的訪問。
主要解決的問題
- 代理模式解決的是在直接訪問某些對象時可能遇到的問題,例如對象創建成本高、需要安全控制或遠程訪問等。
使用場景
- 當需要在訪問一個對象時進行一些控制或額外處理時。
實現方式
- 增加中間層:創建一個代理類,作為真實對象的中間層。
- 代理與真實對象組合:代理類持有真實對象的引用,并在訪問時進行控制。
關鍵代碼
- 代理類:實現與真實對象相同的接口,并添加額外的控制邏輯。
- 真實對象:實際執行任務的對象。
應用實例
- 快捷方式:Windows系統中的快捷方式作為文件或程序的代理。
- 角色扮演:孫悟空作為高翠蘭的代理,豬八戒無法區分。
- 代售點:購買火車票時,代售點作為火車站的代理。
- 支票:作為銀行賬戶資金的代理,控制資金的訪問。
- Spring AOP:使用代理模式來實現面向切面編程。
優點
- 職責分離:代理模式將訪問控制與業務邏輯分離。
- 擴展性:可以靈活地添加額外的功能或控制。
- 智能化:可以智能地處理訪問請求,如延遲加載、緩存等。
缺點
- 性能開銷:增加了代理層可能會影響請求的處理速度。
- 實現復雜性:某些類型的代理模式實現起來可能較為復雜。
使用建議
- 根據具體需求選擇合適的代理類型,如遠程代理、虛擬代理、保護代理等。
- 確保代理類與真實對象接口一致,以便客戶端透明地使用代理。
注意事項
- 與適配器模式的區別:適配器模式改變接口,而代理模式不改變接口。
- 與裝飾器模式的區別:裝飾器模式用于增強功能,代理模式用于控制訪問。
結構
主要涉及到以下幾個核心角色:
-
抽象主題(Subject):
- 定義了真實主題和代理主題的共同接口,這樣在任何使用真實主題的地方都可以使用代理主題。
-
真實主題(Real Subject):
- 實現了抽象主題接口,是代理對象所代表的真實對象。客戶端直接訪問真實主題,但在某些情況下,可以通過代理主題來間接訪問。
-
代理(Proxy):
- 實現了抽象主題接口,并持有對真實主題的引用。代理主題通常在真實主題的基礎上提供一些額外的功能,例如延遲加載、權限控制、日志記錄等。
-
客戶端(Client):
- 使用抽象主題接口來操作真實主題或代理主題,不需要知道具體是哪一個實現類。
實現
我們將創建一個 Image 接口和實現了 Image 接口的實體類。ProxyImage 是一個代理類,減少 RealImage 對象加載的內存占用。
ProxyPatternDemo 類使用 ProxyImage 來獲取要加載的 Image 對象,并按照需求進行顯示。
步驟 1
創建一個接口。
Image.java
public interface Image { void display(); }
步驟 2
創建實現接口的實體類。
RealImage.java
public class RealImage implements Image { private String fileName; public RealImage(String fileName){ this.fileName = fileName; loadFromDisk(fileName); } @Override public void display() { System.out.println("Displaying " + fileName); } private void loadFromDisk(String fileName){ System.out.println("Loading " + fileName); } }
ProxyImage.java
public class ProxyImage implements Image{ private RealImage realImage; private String fileName; public ProxyImage(String fileName){ this.fileName = fileName; } @Override public void display() { if(realImage == null){ realImage = new RealImage(fileName); } realImage.display(); } }
步驟 3
當被請求時,使用 ProxyImage 來獲取 RealImage 類的對象。
ProxyPatternDemo.java
public class ProxyPatternDemo { public static void main(String[] args) { Image image = new ProxyImage("test_10mb.jpg"); // 圖像將從磁盤加載 image.display(); System.out.println(""); // 圖像不需要從磁盤加載 image.display(); } }
步驟 4
執行程序,輸出結果:
Loading test_10mb.jpg
Displaying test_10mb.jpg
Displaying test_10mb.jpg

浙公網安備 33010602011771號