勉強日記

チラ裏

GoF本 Adapter

ねらい

既存クラスのインタフェースを変える

別名

Wrapper

モチベーション

  • 既製品の汎用クラスのインタフェースが合わず、フレームワークで使えなかったり、アプリケーションのクラスと互換性がなかったりする
  • 汎用クラス自体を書き換えるのは現実的でない
    • ソースコードを持っている必要がある
    • 汎用なのに、特定のアプリケーションのインタフェースに合わせるべきではない
  • 汎用クラスのインタフェースだけ変えればよい
  • やり方が2通りある
    • 継承方式
    • 集約方式

つかいどころ

  • あるクラスのインタフェースを変えて、他のクラスとの互換性をもたせたい
  • 【集約方式】インタフェースを変えたい側(Adaptee)が独立して継承ツリーをもっている
    • 継承方式ではサブクラスまでAdaptできない
      • できなくはないけどAdapter派生まみれになるからやめたほうがいい

構造

登場人物

  • Target
    • 満たすべきインタフェース
  • Client
    • Targetインタフェースに依存するクラス
  • Adaptee
    • Targetインタフェースとインタフェースの合わないクラス
    • これにTarget互換をもたせたい
  • Adapter
    • AdapteeをTarget互換にするためのクラス
    • Target派生orTargetを実装するクラス

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

  • ClientはAdapterをTargetとして利用する

功罪

継承方式と集約方式とのトレードオフ

継承 集約
Adapteeとの関係 Adapteeを継承 Adapteeオブジェクトを集約
Adaptee派生クラス対応 不可
Adapteeのオーバライド 不可
間接層 増えない 増える(Adapteeメンバ)

ほか、考えるべきこと

  • AdapteeをTarget互換にするためのAdapterの仕事量はさまざま
    • もともと似てれば大したことはしない
      • メソッド名の読み替えとか
      • 引数の順番を変えるだとか
    • 欠けている機能を補うだとかは重い
  • Pluggable adapters
    • 汎用モジュールの提供を想定
    • ユーザがAdapterを実装しさえすれば、任意のAdapteeを使えるつくりにする
  • 2-way adapters
    • Adapteeとして透過性を残す
      • Target互換にしつつ、Adapteeのインタフェースも残すということ
    • AdapteeのインタフェースとTargetのインタフェースとが大きく異なっていれば多重継承で可能
      • 両方publicで、ということかな

実装

  • 継承方式 in C++
    • Targetはpublic、Adapteeはprivateで継承
      • 外から見たらTargetにしか見えなくなる
  • Pluggable Adapters
    • 汎用モジュールはClientにあたる
    • 「汎用」にするやり方は3つ
      • 継承・オーバライド方式
        • Client自体がTarget
        • 汎用にしたい処理を仮想関数にしておく
        • 利用者にはClientのサブクラスを作らせる(Adapter)
      • 集約・委譲方式
        • 処理を委譲するクラスAdapterインスタンスを受け取る口を用意する
        • 汎用にしたい処理は、Adapterに処理を委譲する
          • ので、Adapterに要求するインタフェースは公開されている必要がある
          • 静的型付け言語では、これをTargetインタフェースとして提供する
          • 動的型付けな言語では、ダックタイピングでもいい
      • パラメータ
        • Smalltalk固有の話?よくわかんなかった

他のStructural Patternとの対比

  • Bridge
    • 構造が似ている
      • 集約のパターンはだいたい似ると思うんですけど
        • StateとStrategyとかね
    • 狙いは異なる
      • Adapter
        • 既存のクラスのインタフェースを変える
      • Bridge
        • インタフェースと実装とを分離する
  • Decorator
    • インタフェースを変えずに(=透過的)機能を追加する
      • 2-way adapterとは似ている
    • Adapterは一般にインタフェースを変えるためのもの
      • 変えた先のインタフェースに合わせるために機能追加を伴うことはある
  • Proxy
    • これもインタフェースを変えない

英語

  • off-the-shelf
    • 既製品の、ありものの
  • viable
    • 実行可能な