Adapterパターンとは
Adapterパターンは、GoF(Gang of Four)によって定義されたデザインパターンの一つで、既存のクラスのインターフェースを、クライアントが期待する別のインターフェースに適合させるためのものです。このパターンを使用することで、既存のクラスに手を加えることなく、異なるインターフェースを持つクラスとして利用できるようになります。
Adapterパターンは、主に以下の二つの手法で実現されます。
1.  継承を利用したAdapter
2.  
委譲を利用したAdapter
 継承を利用したAdapter
継承を利用したAdapterは、既存のクラス(Adaptee)を継承し、必要なインターフェース(Target)を実装するAdapterクラスを作成します。これにより、AdapterクラスはAdapteeクラスの機能を利用しつつ、クライアントが期待するインターフェースを提供できます。
 サンプルプログラム
以下の例では、`Product`クラスが既存のクラスで、修正ができないとします。この`Product`クラスの価格を取得する`getCost()`メソッドを、`getPrice()`メソッドとして利用したい開発者がいるとします。このとき、`ProductAdapter`というAdapterクラスを作成することで、`Product`クラスを修正せずに、異なるインターフェースで`Product`クラスを利用できるようになります。
java
// 既存のクラス(Adaptee)
class Product {
    public int getCost() {
        return 100;
    }
}
// ターゲットインターフェース
interface ProductPrice {
    int getPrice();
}
// Adapterクラス
class ProductAdapter extends Product implements ProductPrice {
    @Override
    public int getPrice() {
        return getCost();
    }
}
public class Main {
    public static void main(String[] args) {
        ProductPrice productPrice = new ProductAdapter();
        System.out.println(productPrice.getPrice()); // Output: 100
    }
}
mermaid
classDiagram
    class Target{
      <
>
      requiredMethod()
    }
    class Adapter{
       requiredMethod()
    }
    class Adaptee{
       oldMethod()
    }
    Target <|-- Adapter : implements
    Adapter --|> Adaptee : extends
    Target : ProductPrice
    Target : getPrice()
    Adapter : ProductAdapter
    Adapter : getPrice()
    Adaptee : Product
    Adaptee : getCost()
 委譲を利用したAdapter
委譲を利用したAdapterは、既存のクラス(Adaptee)のインスタンスをAdapterクラス内に持ち、そのインスタンスを利用して必要なインターフェース(Target)を提供します。この手法では、継承を使用せずにAdapterを実現できるため、より柔軟な設計が可能です。
 サンプルプログラム
java
// 既存のクラス(Adaptee)
class Product {
    public int getCost() {
        return 100;
    }
}
// ターゲットインターフェース
interface ProductPrice {
    int getPrice();
}
// Adapterクラス
class ProductAdapter implements ProductPrice {
    private Product product;
    public ProductAdapter(Product product) {
        this.product = product;
    }
    @Override
    public int getPrice() {
        return product.getCost();
    }
}
public class Main {
    public static void main(String[] args) {
        Product product = new Product();
        ProductPrice productPrice = new ProductAdapter(product);
        System.out.println(productPrice.getPrice()); // Output: 100
    }
}
mermaid
classDiagram
    class Target{
      <>
      requiredMethod()
    }
    class Adapter{
       requiredMethod()
    }
    class Adaptee{
       oldMethod()
    }
    Target <|-- Adapter : implements
    Adapter --* Adaptee : Aggregation
    Target : ProductPrice
    Target : getPrice()
    Adapter : ProductAdapter
    Adapter : getPrice()
    Adaptee : Product
    Adaptee : getCost()
※クラス図において、extendsはimplementsでも良い。
このように、Adapterパターンは、既存のコードを修正することなく、異なるインターフェースを必要とする場合に非常に役立つデザインパターンです。継承と委譲の両方の手法を理解し、状況に応じて適切な方法を選択することが重要です。