Design Patterns : Facrory Method 2018/9

• 一対のインスタンス生成抽象クラス(Factory)とインスタンス定義抽象クラス(Product)を用意し、これらを継承する具象クラスを実装していくパターン。
• 実行クラスからはFactoryクラスを介してProductクラスのインスタンスを生成する 。
• 実行クラスを変更せずともFactoryクラスを変更すれば、生成されるProductクラスインスタンスを変更できる 。

UML

Productクラス(abstract)
// クラス定義の抽象クラス
public abstract class MilitaryPlane {
    
    public abstract int speed();
    
    public abstract int attack();
            
    public abstract int defence();
                   
    public abstract int agile();
                           
    public abstract int bomb();
                                    
    public abstract int torpedo();
                                            
    public abstract String identify();
}

Product具象クラス1
// 零戦クラス
// 単体で性能を変更できる。
public class Zerosen extends MilitaryPlane {
    
    public int speed() { return 500; };
    
    public int attack() { return 100; };
            
    public int defence() { return 0; };
                   
    public int agile() { return 90; };
                            
    public int bomb() { return 60; }
                                   
    public int torpedo() { return 0; }
                                           
    public String identify() {
        return "Zerosen";
    }
}

Product具象クラス2
// 天山艦攻クラス
// 単体で性能を変更できる。
public class Tenzan extends MilitaryPlane {
    
    public int speed() { return 480; };
    
    public int attack() { return 20; };
    
    public int defence() { return 40; };
    
    public int agile() { return 40; };
    
    public int bomb() { return 800; }
    
    public int torpedo() { return 1; }
    
    public String identify() {
        return "Tenzan";
    }
}

Product具象クラス3
// 彩雲クラス
// 単体で性能を変更できる。
public class Saiun extends MilitaryPlane {
    
    public int speed() { return 600; };
    
    public int attack() { return 5; };
    
    public int defence() { return 5; };
    
    public int agile() { return 100; };
    
    public int bomb() { return 0; }
    
    public int torpedo() { return 0; }
    
    public String identify() {
        return "Suiun";
    }
}

Factoryクラス(abstract)
// インスタンス生成クラス
public abstract class Factory {
    
    // インスタンスの生成
    public final MilitaryPlane make() {
        MilitaryPlane plane = makePlane();
        return  plane;
    }
    
    // クラスの実装はサブクラスで行う。
    protected abstract MilitaryPlane makePlane();
}

Factory具象クラス1
// 戦闘機工場
public class AttackerFactory extends Factory {
            
    // 戦闘機作成
    public MilitaryPlane makePlane() {
        // 自クラス内で他のクラスと交換できる。
        return new Zerosen();
    }
}

Factory具象クラス2
// 爆撃機工場
public class BomberFactory extends Factory {
    
    // 爆撃機作成
    public MilitaryPlane makePlane() {
        // 自クラス内で他のクラスと交換できる。
        return new Tenzan();
    }
}

Factory具象クラス3
// 偵察機工場
public class SurveillanceFactory extends Factory {
        
    // 偵察機作成
    public MilitaryPlane makePlane() {
        // 自クラス内で他のクラスと交換できる。
        return new Saiun();
    }
}

Makerクラス
// 制作指示クラス
public class Maker {
    
    // ファクトリーインスタンス
    Factory attackerFactory = new AttackerFactory();
    Factory bomberFactory = new BomberFactory();
    Factory surveillanceFactory = new SurveillanceFactory();
    
    public static enum Demands {
        Attacker, Bomber, Surveillance
    };
    
    // 制作指示
    public MilitaryPlane make(Demands demand) {
        
        // 制作する航空機タイプを指示する。
        switch(demand) {
        case Attacker:
            // 攻撃機の制作指示。中身は工場に任せる。
            return attackerFactory.makePlane();
        case Bomber:
            // 爆撃機の制作指示。中身は工場に任せる。
            return bomberFactory.makePlane();
        case Surveillance:
            // 偵察機の制作指示。中身は工場に任せる。
            return surveillanceFactory.makePlane();
        }
            
        // 指示がなければ作れない。
        return null;
    }
    
    // メイン
    public static void main(String... args) {
    
        Maker maker = new Maker();
       
        // 出来上がるまでものはわからない
        MilitaryPlane plane1 = maker.make(Demands.Attacker);
        System.out.println(plane1.identify());
        MilitaryPlane plane2 = maker.make(Demands.Bomber);
        System.out.println(plane2.identify());
        MilitaryPlane plane3 = maker.make(Demands.Surveillance);
        System.out.println(plane3.identify());
    }
}