導入
「今使っているコードは Printer インタフェースの print(String) を前提にしている。でも新しく使いたいライブラリは OldPrinter の oldPrint(String) というメソッド名しか持っていない」——こういう食い違いは実務でよく起きます。Adapter(アダプタ) は、既存のクラスをラップして、期待されるインタフェースに変換する型です。
説明
コンセント変換プラグのように、Adapterは「呼び出し側が期待する形」と「実際にあるクラスの形」の間に立って、呼び出しを橋渡しします。
public class Main {
public static void main(String[] args) {
Printer p = new OldPrinterAdapter(new OldPrinter());
p.print("こんにちは");
}
}
interface Printer {
void print(String message);
}
class OldPrinter {
void oldPrint(String text) {
System.out.println("[OLD] " + text);
}
}
class OldPrinterAdapter implements Printer {
private OldPrinter oldPrinter;
OldPrinterAdapter(OldPrinter oldPrinter) {
this.oldPrinter = oldPrinter;
}
public void print(String message) {
oldPrinter.oldPrint(message);
}
}
classDiagram
Printer <|.. OldPrinterAdapter
OldPrinterAdapter --> OldPrinter : wraps
class Printer {
<<interface>>
+print(message)
}
class OldPrinter {
+oldPrint(text)
}
OldPrinter… 呼び出し側が期待するPrinterインタフェースを実装していない、既存の(変更できない)クラスです。OldPrinterAdapter implements Printer…Printerを実装しつつ、内部にOldPrinterを1つ保持(ラップ)します。print(String message) { oldPrinter.oldPrint(message); }…Printerとして呼ばれたprintを、内部でOldPrinterのoldPrintに変換して転送しています。Mainから見るとpはただのPrinterです。中身がOldPrinterをラップしていることを意識せずに使えます。
やってみよう
下のエディタを実行して、Printer として呼んだ print("こんにちは") が、内部で OldPrinter.oldPrint に転送されて [OLD] こんにちは と表示されることを確認しましょう。
演習
OldStamp という既存クラス(変更できない想定)を作り、oldStamp(String text) メソッドで STAMP: + text を表示させてください。これを Printer として使えるようにする OldStampAdapter を作り、main から Printer p = new OldStampAdapter(new OldStamp()); p.print("重要"); を呼んで動かしてください。
ヒント1を見る
class OldStamp { void oldStamp(String text) { System.out.println("STAMP: " + text); } }。
ヒント2を見る
class OldStampAdapter implements Printer { private OldStamp oldStamp; OldStampAdapter(OldStamp oldStamp) { this.oldStamp = oldStamp; } public void print(String message) { oldStamp.oldStamp(message); } }。