okinawa

IT勉強メモ

デザインパターン

Factoryパターン

インスタンスの生成をFactoryクラスに集約することで、変更に強くなる。

生産拠点を一つの工場に集中するっちゅうことですね。

Factory methodパターンとはいちおう別物。

・複数クラスが直接クラスBのコンストラクタを呼ぶ場合

    コンストラクタ呼び出し
クラスA →→→→→→→→→→→→ クラスB
クラスC →→→→→→→→→→→→ クラスB
クラスD →→→→→→→→→→→→ クラスB
// これだとクラスBのコンストラクタを変更するとACDも変更必要。

・ファクトリがコンストラクタを呼ぶ場合

     createClassB()     コンストラクタ呼び出し
クラスA →→→→→→→→→→→→ ファクトリ →→→→→→→→→→→→ クラスB
クラスC →→→→→→→→→→→→ ファクトリ →→→→→→→→→→→→ クラスB
クラスD →→→→→→→→→→→→ ファクトリ  →→→→→→→→→→→→ クラスB
// ファクトリクラスのcreateClassB()メソッドだけ変更すればOK

↓こんな感じで直でCクラスのコンストラクタ呼び出すと、もしコンストラクタに変更あったときに、呼び出し側のA・Bも変更が必要になる。

public class A{
     public static void main(String []args){
        C c = newC("山田");
     }
}

public class B{
     public static void main(String []args){
        C c = new C("山田");
     }
}

public class C{
    String name;
    public C(String s){
        this.name = s;
    }
}

↓Factoryクラスを仲介するパターン

public class A{
     public static void main(String []args){
        Factory f = new Factory;
        f.createClassB();
     }
}

public class B{
     public static void main(String []args){
        Factory f = new Factory;
        f.createClassB();
     }
}

public class Factory extends C {
  public void createClassC() {
    C c = new C("山田");
  }
}

public class C{
    String name;
    public C(String s){
        this.name = s;
    }
}

Adapterパターン

継承による方法と委譲による方法がある。今回は継承の方だけ。

Adapterはその名の通り、変換アダプターみたいなもの。

HDMI変換アダプター
HDMI変換アダプター

メリット

既存のクラスを変更せずに済むので、テストが楽になる。

例えばもしバグが発生した場合、既存のクラスが十分にテストされているなら、追加したAdapterとAdapteeのクラスだけをチェックすれば良い。

・DVI→HDMIに変換するコード例↓

既存クラス+Adaptee+Adapter+実行クラスの4つ。

package adapter;
// 既存のクラス
public class Hdmi {

    String maker;
    String originalType;

    Hdmi(String maker, String originalType) {
        this.maker = maker;
        this.originalType = originalType;
    }

    void printMaker() {
        System.out.println(maker);
    }
    
    void printOriginalType() {
        System.out.println(originalType + "からHDMIに変換");
    }
}
package adapter;
// Adapteeクラス
public interface Dvi {
    public void shovMaker();
    public void showOriginalType();

}
package adapter;
// Adapterクラス
public class DviToHdmiAdapter extends Hdmi implements Dvi{
    
    DviToHdmiAdapter(String maker, String originalType) {
        super(maker, originalType);
    }


    @Override
    public void shovMaker() {
        printMaker();
    }


    @Override
    public void showOriginalType() {
        printOriginalType();        
    }
}
package adapter;
// 実行クラス
public class Main {

    public static void main(String[] args) {
        Dvi dvi = new DviToHdmiAdapter("サンワ", "DVI");
        dvi.shovMaker();
        dvi.showOriginalType();
    }
}

運用方法

他にも変換したいケーブルがあれば、AdapterとAdapteeを追加していく。

・追加例

  • USB→HDMI:Adapteeクラス「Usb」Adapterクラス「UsbToHdmiAdapter」
  • VGA:Adapteeクラス「Vga」Adapterクラス「VgaToHdmiAdapter」

参考

Java言語で学ぶデザインパターン入門

デザインパターン ~Adapter~ - Qiita