【オブジェクト指向のこころ】7章 Adapterパターン
「デザインパターンとともに学ぶオブジェクト指向のこころ」の学習記録。
「第7章 Adapterパターン」のまとめ。
Adapterパターンは、クラス(またはクラス群)のインタフェースを、望み通りのインタフェースに変換することが可能になる。
これには望み通りのインタフェースを保持した新規クラスを生成し、既存クラスを包み込むことで、既存クラスのメソッドに対するラッパを実装することになる。
Adapterパターンの目的
GoFによるAdapterパターンの目的は以下の通り。
- あるクラスのインタフェースを、クライアントが望むインタフェースに変換する。
- Adapterによってクラス群は互換性のあるインタフェースを持つことになり、協調して動作できるようになる。
適用例
抽象クラスであるShapeを継承したPoint、Line、Squareがあるとする。
ここにCircleを追加することを考える。
他のクラスと同様に実装する場合、display()
、fill()
、undisplay()
を実装することを考える。
実装するときに既存コードを確認すると、XXCircleという円を表現したクラスが存在することが分かった。
ただし想定していたインタフェース(メソッド名)とは異なっていた。
XXCircleをShapeに合わせてメソッド名を変更すると既存コード全てへ影響が出る。
このような場合、XXCircleには手を付けず、適合(Adapt)することを考える。
具体的には、CircleにXXCircleを保持させる。
Circleオブジェクトに対するリクエストをXXCircleオブジェクトに転送する。
コード例:
class Circle extends Shape { private XXCircle myXXCircle; public Circle() { myXXCircle = new XXCircle(); } @override public void display() { myXXCircle.displayIt(); } }
ここまでの例では、ラッパクラス(Circle)で必要な機能を既存クラス(XXCircle)が全て備えていた。
既存クラスが一部の機能を備えていなければ、ラッパクラスで実装すれば良い。
Adapterパターンの種類
Adapterパターンには2つの種類がある。
Object Adapterパターン
上述の例のように、あるオブジェクトが他のオブジェクトを保持してAdapterを実装する方法。
委譲を利用した方法。
Class Adapterパターン
多重継承を使用してAdapterを実装する方法。
継承を利用した方法。
既存クラスを継承し、求めている処理が呼び出されたとき、既存クラスのメソッドへ転送する。
Facade vs Adapter
FacadeパターンとAdapterパターンは既存クラスを使用したいがインタフェースが期待する状態ではない場合に適用する性質の似たパターンである。
違いとしては以下の通り。
- Facadeパターンはインタフェースを設計し直す必要がないが、Adapterパターンはインタフェースを設計し直す。
- Facadeパターンはポリモーフィズムに則った振る舞いは不要。
- Adapterパターンはポリモーフィズムに則った振る舞いに適用できる。(上述の例のようにShape型としての振る舞わせたい場合に適用できる。単にインタフェースを適合したい場合だけの場合もある。)
Facadeパターンは複数クラスを隠蔽、Adapterパターンは単一クラスの隠蔽、といったイメージがあるが、Facadeが複雑な単一クラスの処理を隠蔽、Adapterが複数のクラスを保持し隠蔽することもあり得る。
つまり以下のような違いがある。
- Facadeパターンはインタフェースを簡素化する
- Adapterパターンは既存のインタフェースを他のインタフェースに変換する