天天看點

dart設計模式之代理模式

代理模式

模式分析

在代理模式(Proxy Pattern)中,一個類代表另一個類的功能。這種類型的設計模式屬于結構型模式。

在代理模式中,我們建立具有現有對象的對象,以便向外界提供功能接口。

模式難點

模式解決問題

在直接通路對象時帶來的問題,比如說:要通路的對象在遠端的機器上。在面向對象系統中,有些對象由于某些原因(比如對象建立開銷很大,或者某些操作需要安全控制,或者需要程序外的通路),直接通路會給使用者或者系統結構帶來很多麻煩,我們可以在通路此對象時加上一個對此對象的通路層。

優點

  1. 你可以在用戶端毫無察覺的情況下控制服務對象。
  2. 如果用戶端對服務對象的生命周期沒有特殊要求, 你可以對生命周期進行管理。
  3. 即使服務對象還未準備好或不存在, 代理也可以正常工作。
  4. 開閉原則。 你可以在不對服務或用戶端做出修改的情況下建立新代理。

缺點

  1. 由于在用戶端和真實主題之間增加了代理對象,是以有些類型的代理模式可能會造成請求的處理速度變慢。
  2. 實作代理模式需要額外的工作,有些代理模式的實作非常複雜。

模式應用場景

按職責來劃分,通常有以下使用場景:

  1. 本地執行遠端服務 (遠端代理)。 适用于服務對象位于遠端伺服器上的情形。
  2. 延遲初始化 (虛拟代理)。 如果你有一個偶爾使用的重量級服務對象, 一直保持該對象運作會消耗系統資源時, 可使用代理模式。
  3. Copy-on-Write 代理。
  4. 通路控制 (保護代理)。 如果你隻希望特定用戶端使用服務對象, 這裡的對象可以是作業系統中非常重要的部分, 而用戶端則是各種已啟動的程式 (包括惡意程式), 此時可使用代理模式。
  5. Cache代理。
  6. 防火牆(Firewall)代理。
  7. 同步化(Synchronization)代理。
  8. 智能引用(Smart Reference)代理。 可在沒有用戶端使用某個重量級對象時立即銷毀該對象。
  9. 記錄日志請求 (日志記錄代理)。 适用于當你需要儲存對于服務對象的請求曆史記錄時。 代理可以在向服務傳遞請求前進行記錄。

模式代碼

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 = "代理模式";
}           

複制