デザインパターン入門Adapterパターンについて
1. Adapterパターンとは
Adapterパターンの概要
Adapterパターンは、既存のクラスにインターフェースを追加するために使用されるデザインパターンの一つです。このパターンでは、2つの異なるクラスを接続するためのAdapterクラスを定義します。Adapterクラスは、既存のクラスが新しいインターフェースをサポートできるように、新しいクラスに必要なインターフェースを提供します。
Adapterパターンの利用目的
Adapterパターンは、以下のような場合に使用されます。
- 既存のクラスに対して新しいインターフェースを追加する場合。
- 既存のクラスと新しいクラスとの間に互換性を持たせる場合。
- 既存のクラスをライブラリやフレームワークに統合する場合。
Adapterパターンを使用することで、既存のクラスの変更を最小限に抑えることができます。また、新しいクラスの開発に時間をかけずに、既存のクラスを再利用することができます。
2. Adapterパターンの種類
クラスによるAdapterパターン
クラスによるAdapterパターンでは、既に存在するクラスをそのまま利用するために、インターフェースを持っていないクラスに対して、インターフェースを実装した新しいクラスを作成します。これにより、既存のクラスを別のクラスに変換し、利用することができます。
インスタンスによるAdapterパターン
インスタンスによるAdapterパターンは、クラスによるAdapterパターンと異なり、既存のクラスのインスタンスを利用するために、インターフェースを持った新しいクラスを作成します。この新しいクラスは、既存のクラスのインスタンスを保持し、そのインスタンスのメソッドを呼び出して処理を行います。
3. Adapterパターンの実装方法
クラスによるAdapterパターンの実装例
クラスによるAdapterパターンは、既存のクラスをAdapterとして利用するパターンです。既存のクラスと新しいインタフェースとの間に変換を行うAdapterクラスを作成し、新しいインタフェースを実装します。以下に、クラスによるAdapterパターンの実装例を示します。
// 既存のクラス
public class OldClass {
public void oldMethod() {
System.out.println("既存のメソッド");
}
}
// 新しいインタフェース
public interface NewInterface {
public void newMethod();
}
// Adapterクラス
public class Adapter extends OldClass implements NewInterface {
public void newMethod() {
oldMethod();
}
}
上記の例では、OldClass
という既存のクラスに新しいインタフェースであるNewInterface
を実装するためのAdapterクラスであるAdapter
を作成しました。Adapter
はOldClass
を継承し、NewInterface
を実装しています。newMethod
メソッドの実装では、oldMethod
メソッドを呼び出しています。
クラスによるAdapterパターンは、既存のクラスを継承するため、既存のクラスのメソッドをそのまま利用できます。ただし、Adapterクラスが1つしか作成できないという制約があるため、複数のAdapterを必要とする場合はインスタンスによるAdapterパターンが適しています。
インスタンスによるAdapterパターンの実装例
インスタンスによるAdapterパターンは、クラスによるAdapterパターンと異なり、継承による実装ではなく、委譲による実装を行います。クラスによるAdapterパターンと同じように、既存のクラスを再利用するため、Adapterクラスを作成します。ただし、Adapterクラスは、既存クラスを継承しないため、既存クラスと同じインターフェースを持ちます。そして、既存クラスを保持するインスタンス変数を持ち、その変数を利用して、既存クラスのメソッドを呼び出します。
以下は、インスタンスによるAdapterパターンの実装例です。既存クラスとして、Adapteeクラスがあります。このクラスには、showMessage()メソッドが定義されています。また、Targetインターフェースがあり、このインターフェースを実装するTargetImplクラスがあります。これらのクラスを利用して、Adapterクラスを作成します。
interface Target {
void printMessage();
}
class TargetImpl implements Target {
public void printMessage() {
System.out.println("Hello World");
}
}
class Adaptee {
public void showMessage() {
System.out.println("こんにちは、世界");
}
}
class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
public void printMessage() {
adaptee.showMessage();
}
}
public class Main {
public static void main(String[] args) {
Target target = new TargetImpl();
target.printMessage();
Adaptee adaptee = new Adaptee();
Target adapter = new Adapter(adaptee);
adapter.printMessage();
}
}
上記の例では、AdapterクラスがTargetインターフェースを実装しているため、Adapterクラスを利用することができます。AdapterクラスのコンストラクタにAdapteeクラスのインスタンスを渡すことで、AdapteeクラスのshowMessage()メソッドを呼び出すことができます。このようにして、既存のクラスを再利用して、新たな機能を実現することができます。
4. Adapterパターンの利用例
ライブラリの互換性の確保
既存のライブラリがあるが、そのライブラリを使用するためのインターフェースがアプリケーションにとって望ましくない場合、Adapterパターンを使用することでインターフェースを変換し、ライブラリを使用できるようにすることができます。
例えば、あるアプリケーションでデータをXML形式で出力する必要があり、既存のライブラリであるJSON形式で出力する関数が提供されている場合、Adapterパターンを使用してJSONをXMLに変換することができます。
新旧システム間の連携
新しいシステムと既存のシステムを連携させる場合、既存のシステムのインターフェースを変更することは困難である場合があります。このような場合に、既存のシステムのインターフェースを新しいシステムが使用するインターフェースに変換するためにAdapterパターンを使用することができます。
例えば、ある企業が新しいシステムを開発し、既存のシステムにある顧客情報を新しいシステムに統合する必要がある場合、既存のシステムの顧客情報を取得するためのAPIが提供されている場合、Adapterパターンを使用してAPIのレスポンスを新しいシステムが使用する形式に変換することができます。
5. Adapterパターンと他のデザインパターンとの関係
AdapterパターンとBridgeパターンの関係
Adapterパターンは、機能を拡張する場合にBridgeパターンと組み合わせて使われることがあります。例えば、Bridgeパターンで異なる実装を持つ複数のクラスがある場合、それらをAdapterパターンでまとめ、統一的に利用することができます。
AdapterパターンとFacadeパターンの関係
AdapterパターンとFacadeパターンは、どちらもインターフェースを提供することで、異なるオブジェクトやシステム間の統合を容易にすることができます。ただし、Adapterパターンは、既存のオブジェクトやシステムのインターフェースに適合するために必要な変換を行うのに対し、Facadeパターンは、複雑なオブジェクトやシステムを単純化するために新しいインターフェースを提供することが目的です。
AdapterパターンとDecoratorパターンの関係
AdapterパターンとDecoratorパターンは、既存のオブジェクトに機能を追加することが目的である点で類似しています。ただし、Adapterパターンは既存のインターフェースに新しい機能を追加することに対し、Decoratorパターンは既存のオブジェクトに新しい機能を追加するために新しいオブジェクトを作成します。また、Decoratorパターンでは、オブジェクトの機能を追加することができるため、Adapterパターンよりも柔軟性があります。
6. まとめ
Adapterパターンのメリット
Adapterパターンのメリットは以下の通りです。
- 既存のクラスを修正することなく、新しいインターフェースを実装できるため、柔軟性が高く、再利用性が高くなります。
- 異なるインターフェースをもつオブジェクト間で互換性を確保することができるため、ライブラリの互換性を確保することができます。
- 新旧システム間の連携を実現できます。
Adapterパターンのデメリット
Adapterパターンのデメリットは以下の通りです。
- Adapterクラスの作成が必要なため、追加のコードが必要になります。
- 過度の使用は、コードの複雑性を増大させる可能性があるため、注意が必要です。
Discussion