デザインパターン入門 | Adapter(アダプタ)パターン
「Adapter(アダプタ)パターン」は、あるクラスの処理を利用する際に、そのクラスとそのクラスを利用する対象の間に「アダプタ」と呼ばれるクラスを作り処理の「中継ぎ」をする役割を担わせるプログラムパターンです。
しかし「言葉だけでは、なかなかイメージが涌かない」という方も多い人のではないでしょうか。
今回は「日常の事例」をテーマに「Adapter(アダプタ)パターン」について見ていきたいと思います。
身近な事例で考える「Adapter(アダプタ)パターン」
車に乗っている方なら馴染みのある「シガーソケット」ですが、家庭用の電化製品を使おうとすると、「インバーター」と呼ばれる電圧変換器を間に設置する必要があります。
例えば、「家庭用の電気ハンドクリーナ」を車の清掃に使おうとすると、

という接続が必要になります。
「Adapter(アダプタ)パターン」では、それぞれの役割ごとに
- Target
- 必要なメソッドを持っている「インターフェース・クラス」。メソッドの実装方法は定めず「抽象メソッド」を定義している。
- Adapter
- 変換するための機能を持つ「クラス」
- Adaptee
- 利用したいメソッドを持っているクラス
Targetとなる「シガーソケット」のインターフェースをJava言語で作成すると下記のようになります。
package SampleAdapter;
public interface CigarSocketTarget {
public abstract void cleanUp();
}
「cleanUpメソッド」は「掃除をする」という内容の抽象メソッドですが、「どのように掃除をする」かは何も定義されていません。
次にAdapteeとなる「ハンドクリーナ」となるクラスを作っていきます。
package SampleAdapter;
public class HandCleanerAdaptee {
public void handCleanUp() {
System.out.println("ハンドクリーナーで車内を掃除しました。");
}
}
次にAdapterとなる「インバーター」となるクラスを作っていきます。
package SampleAdapter;
public class InverterAdapter extends HandCleanerAdaptee implements CigarSocketTarget{
public void cleanUp() {
handCleanUp();
}
}
このクラスでは、「ハンドクリーナ(Adaptee)」を表すクラスを継承し、「シガーソケット(Target)」を表すインターフェースを実装しています。
「CigarSocketTarget」クラスの抽象メソッド「cleanUp」の内容を実装していますが、その中身は、「HandCleanerAdaptee」クラスの「handCleanUp」メソッドを呼び出しています。

このように「Adapter(アダプター)」は「処理の中継ぎ」を行い、「Target」と「Adaptee」を繋ぐ「架け橋」となります。
これらのクラス・インターフェースを利用する「mainメソッド」を持つクラスは下記のようになります。
package SampleAdapter;
public class Main {
public static void main(String[] args) {
InverterAdapter ia = new InverterAdapter();
ia.cleanUp();
}
}
実行結果は、
ハンドクリーナーで車内を掃除しました。
のようになります。
「Adapter(アダプタ)パターン」にはもう一つ「委譲」を利用したパターンもよく知られています。
「委譲」を利用したAdapter(アダプタ)パターン
「InverterAdapter」クラスと「HandCleanerAdaptee」クラスの間に継承関係を作らずに、「InverterAdapter」クラスが「HandCleanerAdaptee」クラスのインスタンスをフィールドに持ちます。

保持しているインスタンス経由で、「HandCleanerAdaptee」クラスの「handCleanUpメソッド」を呼び出します。
このように実装することで、「InverterAdapter」クラスはほかのクラスを継承することができるようになります。
Java言語の場合は、複数のクラスを継承できない(単純継承)という決まりがあるため、このように実装することで、「InverterAdapter」クラスがほかのクラスを継承することができるようになります。
「InverterAdapter」クラスのみが変更されるため、下記のように修正を行います。
package SampleAdapter;
public class InverterAdapter extends CigarSocketTarget {
private HandCleanerAdaptee adpt;
public InverterAdapter() {
this.adpt = new HandCleanerAdaptee();
}
public void cleanUp() {
adpt.handCleanUp();
}
}
コンストラクタで、「adpt」フィールドに「HandCleanerAdaptee」クラスのインスタンスを格納しています。
「cleanUp」メソッドが実行されると、「adpt」フィールド経由で「handCleanUp」メソッドが呼び出されます。
今回は、
- シガーソケット
- インバーター
- ハンドクリーナ
をテーマにしましたが、「直接は使えない」クラスを「間接的に使う」必要がある場合は、「Adapter(アダプタ)パターン」の利用を検討してみはいかがでしょうか。