設(shè)計模式之代理模式
定義
代理模式(Proxy Pattern)是軟件工程中的一種設(shè)計模式,它屬于結(jié)構(gòu)型模式,用于在不直接訪問實際對象的情況下,通過一個或多個代理對象來間接訪問某個對象或執(zhí)行某些操作。
目的
這種模式的主要目的是:
- 控制訪問:代理可以在訪問真實對象之前或之后添加額外的操作,如權(quán)限檢查、延遲初始化、日志記錄等。
- 解耦依賴:代理模式允許將客戶端與真實對象解耦,使得它們之間的依賴關(guān)系通過代理對象來間接實現(xiàn)。
- 增加靈活性:可以在不修改真實對象和客戶端代碼的情況下,通過代理添加或修改行為。
類型
代理模式(Proxy Pattern)是一種常見的設(shè)計模式,它為另一個對象提供一個代替或占位符,以控制對它的訪問。代理模式可以在不修改原始對象的基礎(chǔ)上,通過引入代理對象來添加額外的行為或延遲對象的創(chuàng)建。
代理模式有幾種不同的類型,包括但不限于:
- 遠(yuǎn)程代理(Remote Proxy) :為遠(yuǎn)程對象(位于不同的地址空間)提供局部代表,隱藏對象位于不同地址空間的事實。
- 虛擬代理(Virtual Proxy) :延遲一個資源密集的對象的創(chuàng)建,直到真正需要它的時候。
- 保護(hù)代理(Protection Proxy) :控制對原始對象的訪問,根據(jù)不同的訪問權(quán)限提供不同的訪問策略。
- 智能引用(Smart Reference) :在訪問對象時執(zhí)行額外的動作,比如引用計數(shù)、線程安全檢查等。
- 緩存代理(Cache Proxy) :為結(jié)果提供緩存,加速數(shù)據(jù)訪問。
- 防火墻代理(Firewall Proxy) :在網(wǎng)絡(luò)層面控制對對象的訪問,提供安全控制。
- 同步代理(Synchronous Proxy) :在多線程環(huán)境中,確保對象在同一時間只被一個線程訪問。
優(yōu)缺點
代理模式的優(yōu)缺點如下:
優(yōu)點:
- 對象訪問控制:代理可以在訪問真實對象之前進(jìn)行權(quán)限檢查,控制對敏感對象的訪問。
- 延遲初始化:特別是對于虛擬代理,可以延遲對象的創(chuàng)建,直到真正需要時才進(jìn)行初始化。
- 增加額外的功能:代理可以在不修改真實對象的情況下,通過在調(diào)用前后添加額外的邏輯來擴(kuò)展對象的功能。
- 解耦依賴:代理模式允許客戶端代碼與真實對象解耦,客戶端通過代理對象接口與真實對象交互,降低了組件之間的耦合度。
- 提高性能:通過遠(yuǎn)程代理,可以在本地執(zhí)行某些操作,避免頻繁的網(wǎng)絡(luò)通信,提高系統(tǒng)性能。
- 保護(hù)真實對象:代理可以保護(hù)真實對象不被惡意訪問或濫用,確保對象只承擔(dān)其應(yīng)該承擔(dān)的責(zé)任。
- 代碼復(fù)用:代理對象可以與多個真實對象關(guān)聯(lián),實現(xiàn)代碼的復(fù)用。
缺點:
- 增加復(fù)雜性:引入代理對象會增加系統(tǒng)的設(shè)計復(fù)雜性,需要額外的代碼來維護(hù)代理和真實對象的關(guān)系。
- 可能影響性能:代理對象的額外處理可能會引入延遲,尤其是在需要進(jìn)行復(fù)雜邏輯處理時。
- 代理對象的透明度問題:如果代理對象沒有實現(xiàn)Subject接口的所有方法,可能會導(dǎo)致代理對象的使用不如預(yù)期透明。
- 資源消耗:使用代理模式可能會消耗更多的資源,因為需要創(chuàng)建和維護(hù)代理對象。
- 難以處理所有情況:在某些情況下,代理可能難以處理真實對象的所有方法,特別是當(dāng)真實對象接口發(fā)生變更時,代理對象也需要同步更新。
- 調(diào)試?yán)щy:由于代理模式引入了間接層,調(diào)試時可能難以追蹤問題。
- 代理模式的不適用性:對于一些不需要控制訪問或延遲初始化的對象,使用代理模式可能是一種過度設(shè)計。
代理模式是一種強(qiáng)大的設(shè)計模式,但應(yīng)當(dāng)在適當(dāng)?shù)膱鼍跋率褂?,以確保它帶來的好處大于其引入的復(fù)雜性和潛在的性能開銷。
結(jié)構(gòu)
代理模式通常包含以下角色:
- Subject:定義了真實對象和代理對象的共同接口,這樣代理對象可以在任何真實對象出現(xiàn)的地方使用。
- Real Subject 或 Target:定義了代理所代表的真實對象,包含實際的業(yè)務(wù)邏輯。
- Proxy:包含對真實對象的引用,并提供與真實對象相同的接口。代理對象在訪問真實對象之前或之后可以添加額外的行為。
類圖
以下是使用Mermaid語法繪制的上述代碼的UML類圖:
classDiagram
class Subject {
<<Interface>>
+performTask()
}
class RealSubject {
+ performTask() : void
}
class Proxy {
- realSubject : RealSubject
+ performTask() : void
}
class Client {
- subject : Subject
}
Proxy ..|> Subject : Implements
RealSubject ..|> Subject : Implements
Client ..> Subject : Use
在這個UML類圖中:
- ?
Subject? 是一個接口,定義了performTask()? 方法。 - ?
RealSubject? 是一個類,實現(xiàn)了Subject? 接口及其performTask()? 方法。 - ?
Proxy? 是一個類,也實現(xiàn)了Subject? 接口。它包含一個RealSubject? 類型的私有成員變量realSubject?,以及自己的performTask()? 方法實現(xiàn)。在performTask()? 方法中,如果realSubject? 為null?,則創(chuàng)建RealSubject? 實例。然后,代理在調(diào)用真實對象的performTask()? 方法前后執(zhí)行額外的操作。
示例代碼
代理模式的實現(xiàn)通常涉及到以下幾個角色:
- Subject: 定義了真實對象和代理對象的共同接口。
- Real Subject: 定義了代理所代表的真實對象。
- Proxy: 包含對真實對象的引用,并在與真實對象交互前后可以添加額外的操作。
以下是一個簡單的代理模式Java代碼示例:
// 定義了真實對象和代理對象的接口
interface Subject {
void performTask();
}
// 真實對象
class RealSubject implements Subject {
@Override
public void performTask() {
System.out.println("RealSubject is performing the task.");
}
}
// 代理對象
class Proxy implements Subject {
private RealSubject realSubject;
public Proxy() {
this.realSubject = null;
}
public void performTask() {
if (this.realSubject == null) {
this.realSubject = new RealSubject();
}
// 在訪問真實對象之前添加額外的操作
System.out.println("Proxy preparing RealSubject for the task.");
this.realSubject.performTask();
// 在訪問真實對象之后添加額外的操作
System.out.println("Proxy finalizing after task.");
}
}
// 客戶端
public class Client {
public static void main(String[] args) {
Subject subject = new Proxy();
subject.performTask();
}
}
在這個例子中,Proxy?類在調(diào)用RealSubject?之前和之后添加了額外的輸出操作,演示了如何在不修改原始對象的情況下,通過代理添加額外的行為。代理模式非常適用于需要控制對象訪問、延遲對象創(chuàng)建、或者為對象添加額外功能的場景。
應(yīng)用場景
代理模式在軟件開發(fā)中有許多應(yīng)用場景,以下是一些常見的例子:
- 遠(yuǎn)程代理:當(dāng)需要與遠(yuǎn)程對象(如Web服務(wù))交互時,可以使用代理來隱藏對象位于不同地址空間的事實。
- 虛擬代理:當(dāng)創(chuàng)建一個對象需要消耗大量資源時(例如,加載大型圖像或文檔),可以使用虛擬代理來延遲對象的創(chuàng)建,直到它真正需要被使用。
- 保護(hù)代理:當(dāng)需要控制對原始對象的訪問時,可以使用保護(hù)代理來檢查調(diào)用者是否有權(quán)限執(zhí)行某些操作。
- 智能引用:在內(nèi)存管理或?qū)ο笠糜嫈?shù)的場景中,智能引用代理可以在對象被引用或釋放時執(zhí)行額外的操作。
- 緩存代理:為結(jié)果提供緩存,加速數(shù)據(jù)訪問。如果對象的創(chuàng)建是昂貴的,緩存代理可以存儲結(jié)果以便快速訪問。
- 防火墻代理:在網(wǎng)絡(luò)安全領(lǐng)域,防火墻代理可以控制對特定資源的訪問,提供訪問控制和安全檢查。
- 同步代理:在多線程環(huán)境中,同步代理確保對象在同一時間只被一個線程訪問,從而避免競態(tài)條件。
- 延遲初始化:當(dāng)對象的初始化依賴于一些不確定或昂貴的條件時,可以使用代理來延遲初始化過程。
- 日志記錄和監(jiān)控:代理可以在調(diào)用真實對象的方法前后添加日志記錄或性能監(jiān)控代碼。
- 事務(wù)管理:在需要事務(wù)控制的場景中,代理可以在方法調(diào)用前后添加事務(wù)開始和提交或回滾的邏輯。
- 訪問對象的限流:代理可以控制對某些資源的訪問頻率,例如API調(diào)用的限流。
- 實現(xiàn)功能擴(kuò)展:通過代理可以在不修改原有對象的基礎(chǔ)上,動態(tài)地添加額外的功能。
- 網(wǎng)絡(luò)資源訪問:當(dāng)訪問網(wǎng)絡(luò)資源時,代理可以在本地緩存數(shù)據(jù),減少網(wǎng)絡(luò)請求。
- 圖形用戶界面(GUI) :在GUI編程中,代理模式可以用于實現(xiàn)命令的撤銷和重做功能。
- 裝飾者模式的替代:在某些情況下,代理模式可以作為裝飾者模式的替代,用于動態(tài)地添加額外的職責(zé)。
代理模式的核心優(yōu)勢是它提供了一種靈活的方式來擴(kuò)展或修改對象的行為,而不需要改變對象本身的代碼。這有助于遵循開閉原則(對擴(kuò)展開放,對修改封閉)。
?

浙公網(wǎng)安備 33010602011771號