本文へスキップ
BecomeCoder

Javaデザインパターンコース · 第3章 構造に関するパターン ― オブジェクトの「組み合わせ方」を工夫する · レッスン6

Adapter ― インタフェースの不一致を橋渡しする

ブラウザで完結

導入

「今使っているコードは Printer インタフェースの print(String) を前提にしている。でも新しく使いたいライブラリは OldPrinteroldPrint(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 PrinterPrinter を実装しつつ、内部に OldPrinter を1つ保持(ラップ)します。
  • print(String message) { oldPrinter.oldPrint(message); }Printer として呼ばれた print を、内部で OldPrinteroldPrint変換して転送しています。
  • 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); } }

実際に動かしてみよう

下のエディタにJavaを書いて「実行」を押すと、学習用シミュレータが System.out.println の出力を表示します(本物のJVMではなく、教材の範囲を再現した軽量エンジンです)。クラス・継承・コレクションなども動きます。Scanner で入力を読む例は「標準入力」欄に値を入れてください。本文の例を書き換えて動かしてみましょう(Stream・ラムダ・スレッド・ファイル入出力など一部の機能は対象外です)。

Java — ブラウザ内で実行(学習用シミュレータ)

Javaの教材サブセットを動かす学習用シミュレータを読み込みます(本物のJVMではなく、動きを再現した軽量な自作エンジンです)。
スクロールして表示された時点でも自動で読み込まれます。