GoF本 Adapter

GoFデザインパターン勉強メモ

ねらい

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

別名

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

    • 実行可能な