Javaで学ぶデザインパターン

アダプター

クロード
そうですね、おっしゃる疑問はとても的確です。アダプターパターンの本当のメリットについて、もう少し具体的に説明します。
アダプターパターンの本当のメリット
ライブラリやサードパーティのコードを変更できない場合
外部ライブラリやフレームワークのコードは直接修正できません。例えば、あなたがJSONを扱うライブラリを使っているとして、あなたのシステムはXMLを扱うインターフェースしか持っていないとします。このとき、JSONライブラリのコードを修正できないので、アダプターを作成して互換性を持たせます。
レガシーコードとの共存
古いシステムを完全に書き換えるのではなく、段階的に新システムに移行したい場合、アダプターは橋渡し役として機能します。
依存関係の逆転
例えば以下のような状況を考えてみましょう:

等は変更の加えることのできないクラスに対してアダプタ(仲介)を介して処理等を行い呼び出すため。インターフェースを設ける。そのインターフェースと使いたいクラスを継承したアダプタークラスを作成。アダプタークラス(インターフェース)を介して呼び出したいクラスを扱う感じ

Aというインターフェースがある。それを継承させたBクラスがある。
A b = new B();とする時と、
B b = new B();としてインスタンスを生成する際の違いは何か?
編集
Javaでは、Aインターフェースを実装したBクラスのインスタンスを生成する際、変数の型宣言をAにするかBにするかによって重要な違いが生じます。
A b = new B(); と B b = new B(); の違い
アクセスできるメンバーの範囲:
A b = new B(); - 変数bはAインターフェースで定義されたメソッドにのみアクセスできます
B b = new B(); - 変数bはAインターフェースのメソッドに加えて、Bクラスで追加されたメソッドやフィールドにもアクセスできます
コード例:
java
コピー
interface A {
void methodA();
}
class B implements A {
@Override
public void methodA() {
System.out.println("Method A from B");
}
public void methodB() {
System.out.println("Method B");
}
}
public class Main {
public static void main(String[] args) {
A a = new B();
a.methodA(); // OK
// a.methodB(); // コンパイルエラー - AインターフェースにmethodB()はない
B b = new B();
b.methodA(); // OK
b.methodB(); // OK - BクラスにはmethodB()がある
}
}
多態性の活用:
A b = new B();は多態性を活用した書き方です
インターフェースに依存するコードになるため、将来Bの代わりにAを実装した別のクラスCに置き換えやすくなります
柔軟性とカプセル化:
A b = new B();はクライアントコードを実装の詳細から切り離します
実装クラスの詳細よりも、インターフェースの機能に注目したコードになります
実際の使い所:
メソッドの引数: void process(A param) のように引数の型をインターフェースにすると、Aを実装した任意のクラスのインスタンスを渡せます
コレクション: List<A> items = new ArrayList<>(); のようにすると、Aを実装した多様なオブジェクトを同じリストで管理できます
基本的に、可能な限り具体的な実装ではなくインターフェース型の変数を使うことで、より柔軟で拡張性の高いコードを書くことができます。これは「インターフェースに対してプログラミングする」というオブジェクト指向プログラミングの重要な原則の実践です。