今年から、花粉症になったみたいです・・・。
鼻がムズムズして頭も痛くなるし大変ですね、なめてました。
今回は、
Adapterパターン
について書きます!
Adapterパターン
クラスのインターフェースを、
クライントの期待する別のインターフェースに変換する。
アダプタは互換性がないインターフェースのために、
そのままでは連携ができないクラス(Adaptee)を
(Clientと)連携できるようにさせます。
ラップするインターフェースを変換します。
▶︎ Adapter
Targetインターフェースを実装する。
▶︎ Target <<interface>>
ClientはこのTargetインターフェースを使っている感覚。
実際には、Adapterを通して、Adapteeを使っているが、
Adapteeを使っている認識は特にない。
▶︎ Adaptee
全てのリクエストはAdapeeに委譲される。
Adapteeの任意のサブクラスにもAdapterは適用できる
(コンポジションのため)
▶︎ Client
①Targetインターフェースを使って、
Adapterのメソッドを呼び出し、
Adapterにリクエストをする。
②AdapterがAdapteeインターフェースを使って
Adapteeのメソッドに変換して呼び出す
③Clientはリクエスト結果を受け取るが、
Targetインターフェースに沿っただけなので
変換をしてくれたAdapterの存在は知らない。
オブジェクトアダプタ/クラスアダプタ
実は、Adapterパターンには、
– オブジェクトアダプタ
– クラスアダプタ
の2つがある。
オブジェクトアダプタ
コンポジションを使うので、
Adapteeとそのサブ(具象)クラスにも適用可能、多様性あり。
クラスアダプタ
(多重)継承を使うので、
1つの特定のアダプティに特化したアダプタが実装可能。
オーバライドができる。
いいところ
・Adapterパターンを使わずに、互換性対応のために、
Client側のインターフェースに対する全ての実装を変更する場合、
多くのコード変更やそれによる影響調査などコストが高い
(例)TurkeyインターフェースをDockインターフェースへの互換性対応のために、
Turkeyインターフェースを変更する場合
– Turket.php
interface Turkey { - public function gobble(): void; + public function quack(): void; public function fly(): void; }
– WildTurkey.php(Turkeyインターフェースを実装する具象クラス)
他にも具象クラスがあれば、
全ての具象クラスのgobbleメソッドの修正が必要となる。
class WildTurkey implements Turkey { - public function gobble(): void + public function quack(): void { echo "ゴロゴロ\n"; } }
↓
↓ Adapterを使うと…
↓
1つのクラス内にすべての変更をカプセル化したクラスを提供できる。
Client/Adaptee/TargetInterfaceのコード変更は不要。
双方向アダプタを作ることも可能
実際に作ってみた!しかし、テキトーすぎて見せたくない。。。
時間あったらちゃんとさせます。
– DockAndTurkeyAdapter.php
class DockAndTurkeyAdapter implements DockAndTurkey { /* @var Turkey $turkey */ public $turkey; /* @var Dock $dock */ public $dock; public function __construct($turkeyOrdock) { if($turkeyOrdock instanceof Turkey) $this->turkey = $turkeyOrdock; if($turkeyOrdock instanceof Dock) $this->dock = $turkeyOrdock; } public function quack(): void { $this->turkey->gobble(); } public function gobble(): void { $this->dock->quack(); } public function fly(): void { if($this->turkey !== null){ for($i = 0; $i < 5; $i++){ $this->turkey->fly(); } } else { $this->dock->fly(); } } }
– DockAndTurkey.php
DockインターフェースとTurkeyインターフェースの拡張インターフェース
use HFD\Adapter\Dock\Dock; use HFD\Adapter\Turkey\Turkey; interface DockAndTurkey extends Dock,Turkey { }
interfaceのextendsって初めて使いました。
こうやって使うんですね\(^^)/