Adapter パターンを考えます。

デザインパターンを調べ始めた経緯はこちらです。

他のパターンはこちらです。

今回もこちらの本を読み解いていきます。

オブジェクト指向における再利用のためのデザインパターン

Adapter とは日本語に直すとどのような意味になるのでしょうか?

直訳すれば「適合させるもの」

引用元URL:https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%80%E3%83%97%E3%82%BF%E3%83%BC

"適合"という単語から二つ以上の何かを合わせるようなイメージが浮かびます。


本でのカタログにあるAdapter パターンは、パターンの目的から始まります。そして、パターンを適用する動機として仮の問題を想定し、その解決策がAdapter パターンであることを示します。

その後、パターンの有効な条件・構造・特徴・実装・サンプルコード・使用例・関連するパターンと内容が続きます。

今回は"特徴"までを考えていきます。


※かなり紆余曲折することや誤った解釈をする可能性があります。その際は是非コメントをお待ちしています。よろしくお願いします。

※本の項目通りに進めずにAdapter パターンを自身が理解した過程で再構成しています。

でははじめます。


Adapter パターンの目的

あるクラスのインタフェースを、クライアントが求める他のインタフェースへ変換する。Adapterパターンは、インタフェースに互換性のないクラス同士を組み合わせることができるようにする。

少しづつ読み解いていきます。

クラス

A class defines an object's interface and implementation. It specifies the object's internal representation and defines the operations the object can perform.

引用先URL:http://www.cs.unc.edu/~stotts/GOF/hires/chapAfso.htm#class

翻訳すると

クラスにはオブジェクトのインタフェースと実装を定義します。そのオブジェクトの内部を象徴的に表す様に指定をし、それとともに実行できる操作(部分)を定義します。

少しややこしくなってしまいましたが、簡単に書くと

クラスはオブジェクトのインタフェースと実装(処理・仕掛け・仕組み)を用意して、そのオブジェクトで実装した内容を外部から操作出来る部分も用意しますよーということだと解釈しました。

インタフェース
情報を交換するための共有境界・やり取りする部分
(※独自の理解です。)

クライアント
その動作の一部として、あるサービスにアクセスする他のプログラムやコンピュータのハードウェアまたはソフトウェアに要求を送信するコンピュータまたはプログラムのことである。

wikipedia英語版の翻訳です。「ユーザの指示や命令のこと」と解釈しました。

※デザインパターンに出てくる専門用語翻訳集的な記事の必要性を感じたので、次回投稿しようと思います。

これらを踏まえてAdapterパターンの目的は、

クラスの持つやり取りする部分がユーザがやり取りしたい情報・もしくは部分と異なっていたので、そのクラスとやり取り出来るように変換する部分を作ります。この変換はやり取りする部分の違うクラス同士にも役に立ちます。

と解釈しました。

生活の例を出すと「変換アダプター」ということになると思います。最初からこの例を出せば良かったのですが、デザインパターンが定義するAdapterを意訳しようと奮闘してみました。


Adapter パターンの構造

画像1

画像2

引用先URL:http://www.cs.unc.edu/~stotts/GOF/hires/pat4afso.htm#participants

上の図はClientがやり取りするTargetクラスとTargetクラスから呼び出したいけどやり取りする部分(インタフェース)が全然違うためやり取りができないAdapteeクラス、この2クラスをAdapterクラスが多重継承することでTargetからAdapteeクラスの処理を呼び出している様子です。


下の図はわかりやすい例があったのでこちらをご覧ください。

画像4

引用先URL:https://refactoring.guru/design-patterns/adapter

穴とその穴にすっぽり収まる円柱があり、穴に収まるような直方体が欲しい時、直方体を生み出すクラスはすでにあるので四角はそのクラスから呼び出します。そして円柱に見せかけるように擬似的に半径を設定できる仕組みを用意することで、

”いでよこの半径の円柱そして直方体よ”

と半径を指定するだけで呼び出せるようにしてしまうという図です。


構成要素をまとめます。

Targetクラス
Clientが使用するドメイン固有のインタフェース(情報をやり取りする部分)を定義しています。

Clientクラス
Targetのインタフェース(情報をやり取りする部分)に従ってオブジェクトと連携します。

Adapteeクラス
既存のインタフェース(情報をやり取りする部分)が定義されている適合させたいクラス。

Adapterクラス
AdapteeクラスのインタフェースをTargetクラスのインタフェースに適合させるクラス。


Adapter パターンの特徴

クラスアダプタ(多分多重継承の方)

Adaptee クラスのTarget への適応は具体的なAdapter クラスに任せます。そのため、あるクラスとそのサブクラスすべてを適応させたい場合には、 クラスアダプタは使えません。

AdapterはAdapteeのサブクラスであるため、Adapteeの動作の一部をAdapterにオーバーライドさせることができます。
1つのオブジェクトだけを導入するので、 Adapterクラスからのポインタへの間接的な接続は必要ありません。


オブジェクトアダプタ(穴と円柱と直方体の方)

1つのAdapterクラスで多くのAdapteeクラスを扱うことができます。もちろんAdapteeクラス自身とそのサブクラス(もしあれば)を扱うこともできます。加えて、AdapterクラスはすべてのAdapteeクラスに一度に機能を追加することができます。

注意点としてAdapteeクラスの動作をオーバーライドすることが難しくなります。Adapteeクラスをサブクラス化し、AdapterクラスがAdapteeクラス自体ではなくサブクラスを参照するようにする必要があります。


Adapterパターンを使用する際に考慮すべき問題を以下に示します。

1.Adapterはどのくらい適応できるのか?
Adapterクラスは、AdapteeクラスをTargetクラスのインタフェースに適応させるために行う作業の量は、TargetクラスのインタフェースがAdapteeクラスとどれだけ似ているかに依存します。

2.Pluggable adapters(接続可能なAdapter)
使用するために必要な前提条件を最小限にしたクラスは、他のクラスの再利用性が高まります。
他のクラスはAdapterクラスに対して常に同じインタフェースを見なければいけないという前提がありますが、クラスにインタフェースの適応機能を組み込むことで、その前提を排除することができます。
別の言い方をすると、インタフェースの適応機能により、クラスに対して異なるインタフェースを想定している既存のシステムに、自分のクラスを組み込むことができます。
"ObjectWorks\Smalltalk [Par90]"では、インタフェース適応機能を組み込んだクラスをPluggable Adapterと呼んでいます。

3.双方向アダプタに使って透明性を確保する。
アダプタの潜在的な問題は、すべてのクライアントに対して透過的ではないということです。適応されたオブジェクトは、もはやAdapteeのインタフェースに準拠していないので、Adapteeオブジェクトが使用できる場所では、そのまま使用することはできません。双方向アダプタはそのような透過性を提供することができます。具体的には、2つの異なるクライアントが1つのオブジェクトを異なる方法で見る必要がある場合に有効です。


Adapter パターンの有効な条件

Adapterパターンは次のような条件において有効に使うことができます。

・既存のクラスを利用したいが、そのクラスのインタフェースが必要なインタフェースと一致していない場合。

・まったく無関係で予想もつかないようなクラス(必ずしも互換性のあるインタフェースを持つとは限らない)とも強調していける、再利用可能なクラスを作成したい場合。

・再利用可能なクラスを作成して、関連性のないクラスや予期せぬクラス、つまり、必ずしも互換性のあるインターフェイスを持たないクラスと連携させたい場合。

・(オブジェクトアダプタのみ)既存のサブクラスを複数利用したいが、それらすべてのサブクラスをさらにサブクラス化することで、そのインタフェースを適合させることが現実的でない場合。オブジェクトに適用するAdapterパターンでは、その親クラスのインタフェースを適合させると良いです。

・(オブジェクトアダプタのみ)複数の既存サブクラスを使用する必要があるけれども、すべてのサブクラスに対してサブクラス化を行いインターフェースを適合させるのは非現実的で難しい場合。オブジェクトアダプタは、その親クラスのインタフェースを適応させることができます。


今回はイメージしやすいパターンでしたが特徴や気を付けることが込み入っており、シンプルなことほど気をつけなければいけないということを実感しました。

翻訳のみで終わらせてしまった箇所も多々ありますのでまた加筆・修正行えたらと思います。

最後まで読んでくださりありがとうございます。


参考サイト



この記事が気に入ったらサポートをしてみませんか?