代理模式
模式分析
在代理模式(Proxy Pattern)中,一個類代表另一個類的功能。這種類型的設計模式屬于結構型模式。
在代理模式中,我們建立具有現有對象的對象,以便向外界提供功能接口。
模式難點
模式解決問題
在直接通路對象時帶來的問題,比如說:要通路的對象在遠端的機器上。在面向對象系統中,有些對象由于某些原因(比如對象建立開銷很大,或者某些操作需要安全控制,或者需要程序外的通路),直接通路會給使用者或者系統結構帶來很多麻煩,我們可以在通路此對象時加上一個對此對象的通路層。
優點
- 你可以在用戶端毫無察覺的情況下控制服務對象。
- 如果用戶端對服務對象的生命周期沒有特殊要求, 你可以對生命周期進行管理。
- 即使服務對象還未準備好或不存在, 代理也可以正常工作。
- 開閉原則。 你可以在不對服務或用戶端做出修改的情況下建立新代理。
缺點
- 由于在用戶端和真實主題之間增加了代理對象,是以有些類型的代理模式可能會造成請求的處理速度變慢。
- 實作代理模式需要額外的工作,有些代理模式的實作非常複雜。
模式應用場景
按職責來劃分,通常有以下使用場景:
- 本地執行遠端服務 (遠端代理)。 适用于服務對象位于遠端伺服器上的情形。
- 延遲初始化 (虛拟代理)。 如果你有一個偶爾使用的重量級服務對象, 一直保持該對象運作會消耗系統資源時, 可使用代理模式。
- Copy-on-Write 代理。
- 通路控制 (保護代理)。 如果你隻希望特定用戶端使用服務對象, 這裡的對象可以是作業系統中非常重要的部分, 而用戶端則是各種已啟動的程式 (包括惡意程式), 此時可使用代理模式。
- Cache代理。
- 防火牆(Firewall)代理。
- 同步化(Synchronization)代理。
- 智能引用(Smart Reference)代理。 可在沒有用戶端使用某個重量級對象時立即銷毀該對象。
- 記錄日志請求 (日志記錄代理)。 适用于當你需要儲存對于服務對象的請求曆史記錄時。 代理可以在向服務傳遞請求前進行記錄。
模式代碼
abstract class Subject {
void request();
}
class RealSubject implements Subject {
const RealSubject();
@override
void request() {
print("RealSubject:正在連接配接");
}
}
class SubjectProxy implements Subject {
final RealSubject _realSubject;
const SubjectProxy(this._realSubject);
@override
void request() {
if (this._checkAccess()) {
this._realSubject.request();
this._logAccess();
}
}
bool _checkAccess() {
print("Proxy: 判斷目前是否可連接配接");
return true;
}
void _logAccess() {
print("Proxy: 寫一些日志比如連接配接時間");
}
}
class RunProxy implements Run {
@override
void main() {
print('Client: 使用RealSubject類:');
const realSubject = const RealSubject();
_clientCode(realSubject);
print('');
print('Client: 使用代理類:');
const proxy = const SubjectProxy(realSubject);
_clientCode(proxy);
}
_clientCode(Subject subject) {
// ...
print('做一些連接配接前的事情');
subject.request();
// ...
}
@override
String name = "代理模式";
}
複制