勉強日記

チラ裏

GoF本 Proxy

ねらい

  • あるオブジェクトの代理やプレースホルダを提供し、アクセス制御を実現する

AKA

  • Surrogate

モチベーション

  • ドキュメントエディタ上の画像オブジェクトの例
    • 画像はコスト高い
    • 最初から全部は見えてないので、最初に全部読み込む必要はない
    • 見えるようになってから読み込めばいい
  • 画像を遅延初期化することにより・描画・テキスト成形のロジックに影響が及ぶべきではない
  • 画像のプロキシImageProxyを導入することで解決する
    • 利用側からは画像オブジェクトと区別がつかない(同じインターフェース)
    • 画像オブジェクトの初期化の責務を担う
    • 幅高さ情報ももつ
      • 画像オブジェクト読み込み前はとりあえず0とかを返す
      • 読み込み後は、画像の幅高さを返す

つかいどころ

Remote Proxy

  • 異なるアドレス空間のオブジェクトを仲介するプロキシ
  • Ambassador (大使)とも
    • 国境をまたぐイメージからか

Virtual Proxy

  • 遅延生成・遅延初期化を行うプロキシ

Protection Proxy

  • アクセス制御を行うプロキシ

Smart Reference

  • 裸のポインタを置き換えるもの
    • std::shared_ptr<T>
      • 参照カウント、0になったら解放
    • 永続データのアクセサ (DAO: Data Access Object)
    • 排他制御つきのアクセサ
      • なんか名前あるんだろうか

登場人物

  • Proxy
    • RealSubjectへの参照を保持する
    • RealSubjectSubjectとのインタフェースが一致していれば
      (= RealSubjectのインタフェースがSubjectのスーパーセットでなければ)
      Subjectへの参照を保持することもある
    • Subjectインタフェースを実装する
      • RealSubjectと置換できるよう
    • RealSubjectへのアクセス制御や、生成・初期化・解放の責務を負う
    • 種類別の責務
      • Remote Proxy
      • Virtual Proxy
        • RealSubjectオブジェクトの生成を遅延させられるよう、
          追加の情報をもつことがある
          • ImageProxyの幅高さ0、など
      • Protection Proxy
        • 呼び元の認可
  • Subject
    • RealSubjectProxyに共通のインタフェースを与える
  • RealSubject
    • Proxyが代理をつとめる対象のオブジェクトのクラス

クライアントコードからの利用

  • クライアントコードはSubjectに対して操作を行う
  • Proxyはこれを受け取り、RealSubjectに良しなに仲介する
    • 「良しなに」はProxyの種類によりけり

結果

  • 中間層が1つ追加されることにより・・・
    • Remote Proxy
    • Virtual Proxy
      • 遅延生成・遅延初期化できる
    • Protection Proxy/Smart Reference
      • オブジェクトアクセスの前後でなんかできる
        • アクセス拒否
        • 参照カウント
          • カウント0でオブジェクト解体・メモリ解放
  • copy-on-write
    • 巨大なオブジェクトのコピーで有用
    • 実際にコピーが必要になるまで、複製処理を遅延する
      • modificationが生じないかぎり不必要
    • Virtual ProxyとSmart Referenceとの合わせ技といえるかも

実装にあたり考えるべきこと

言語の機能を使うと幸せになれることも

演算子オーバーロード

  • C++->とか*とか
    • Virtual Proxyなんかで有用
    • Protection Proxyのように、一部の操作のみRealSubjectに取り次ぎたいような場合には不適切

マジックメソッド(って一般的なワードなんだろうか)

  • 未定義のメソッドが呼び出されたときに呼ばれるやつ
  • doesNotUnderstand:の弱点
    • 言語組み込みの一部の操作については呼ばれない
    • もともと例外処理用であり、速度が遅い
  • 無限再帰に注意する

Proxyが包むオブジェクトの型

  • RealSubjectSubject派生なので、インタフェースはスーパーセットになる
  • インタフェースが一致していれば、ProxySubjectを集約してもいい
    • すべてのRealSubjectProxyでさえも一様に扱える
  • Virtual Proxy等、特定のRealSubjectをインスタンシエートしなければならない場合は、その具象クラスのオブジェクトを集約する

関連するパターン

  • Adapterとの対比
    • Adapterは、Adapteeと異なるインタフェースを提供する
    • Proxyは、基本的にRealSubjectと同じインターフェースを提供するが、
      Protection Proxyはこの限りではない
      • 操作を認可しない場合、インタフェースはサブセットになる
  • Decorator
    • 実装は似ているが目的が異なる
      • Decorator: インタフェースをそのままに、オブジェクトに責務を追加する
      • Proxy: オブジェクトのアクセス制御を行う
    • 【所感】というか集約のパターンの実装はどれも似たり寄ったりだと思う
    • Proxyの種類によっては、実装が似通わなくなるケースもある
      • Remote Proxy
        • オブジェクトそのものの参照はもたず、間接的な参照をもつ
      • Virtual Proxy
        • 最初はオブジェクトそのものの参照はもたず、間接的な参照をもつ
          • ファイル名とか

英語

  • Ambassador
    • 大使
      • 国をまたぐ代理人、というかんじ
      • こういう比喩すき
  • Housekeeping
    • 【計算機】後始末処理
      • Dispose()とか