Adapterパターンの実装例 (Java)
[履歴] (2013/08/16 03:38:14)

概要

何か新しい機能Targetが必要となった際に、既に十分な運用実績があり信頼できるクラスAdapteeがある場合において、もしもそのクラスAdapteeを使い回して新しい機能Targetが実現できるのであれば、1から実装し直すよりも手間が省けます。既存のクラスAdapteeが要求仕様を満たすように適合させるものAdapterを用意することでこれを実現します。AdapterはWrapperとよばれることもあります。

要求仕様Targetがinterfaceで与えられている場合

既存の信頼できるクラスAdapteeが、SSV (Space separated values) を出力する機能を有しているとします。これをAdapterでラップして、新たな要求仕様Targetがinterfaceで指示する通り、CSVで出力できるようにします。

sample.java

interface Target {public abstract String getCsv();}

class Adaptee {
    private int arr[];
    public Adaptee(int arr[]) {this.arr=arr;}
    public String getSsv() { //Space separated values
        StringBuilder sb = new StringBuilder();
        for(int i=0; i<arr.length; ++i) {
            sb.append(arr[i]);
            if(i<arr.length-1) sb.append(" ");
        }
        return sb.toString();
    }
}

class Adapter extends Adaptee implements Target {
    public Adapter(int arr[]) {super(arr);}
    public String getCsv() {
        String str = getSsv();
        StringBuilder sb = new StringBuilder();
        for(int i=0; i<str.length(); ++i) {
            if(str.charAt(i) == ' ') sb.append(',');
            else sb.append(str.charAt(i));
        }
        return sb.toString();
    }
}

class Sample {
    public static void main(String args[]) {
        int arr[] = {1,2,4,8,16};
        Target target = new Adapter(arr);
        System.out.println(target.getCsv());
    }
}

実行例

$ javac sample.java && java Sample
1,2,4,8,16

要求仕様Targetが抽象クラスで与えられている場合

Javaでは多重継承ができないため、要求仕様Targetが抽象クラスで与えられている場合は、AdapterはAdapteeを先程のようにextendsするのではなく、メンバ変数としてhasし委譲することによってAdapteeを利用します。

sample.java

abstract class Target {public abstract String getCsv();}

class Adaptee {
    private int arr[];
    public Adaptee(int arr[]) {this.arr=arr;}
    public String getSsv() { //Space separated values
        StringBuilder sb = new StringBuilder();
        for(int i=0; i<arr.length; ++i) {
            sb.append(arr[i]);
            if(i<arr.length-1) sb.append(" ");
        }
        return sb.toString();
    }
}

class Adapter extends Target {
    private Adaptee adaptee;
    public Adapter(int arr[]) {adaptee=new Adaptee(arr);}
    public String getCsv() {
        String str = adaptee.getSsv();
        StringBuilder sb = new StringBuilder();
        for(int i=0; i<str.length(); ++i) {
            if(str.charAt(i) == ' ') sb.append(',');
            else sb.append(str.charAt(i));
        }
        return sb.toString();
    }
}

class Sample {
    public static void main(String args[]) {
        int arr[] = {1,2,4,8,16};
        Target target = new Adapter(arr);
        System.out.println(target.getCsv());
    }
}

実行例

$ javac sample.java && java Sample
1,2,4,8,16
関連ページ