デザインパターン #8 〜Abstract Factory〜

第８回目 **Abstract Factoryパターン**

# 概要
Abstract Factoryパターンは、関連の一連のオブジェクト群をまとめて生成する方法を提供するパターン。 このパターンを適用すると, 上記関連オブジェクトグループ単位での入れ替え, 追加が容易に行える。
よく似たパターンに **Factory Methodパターン** があるが、 **Factory Methodパターン** は、オブジェクト生成の抽象化にポイントを置いたパターンであるのに対し、**Abstract Factoryパターン** は、関連するオブジェクト群をまとめて生成するための手順の抽象化にある。
# サンプル
今回は「朝食」「昼食」「夕食」それぞれの献立を作るクラスをAbstractFactoryパターンを適用して生成したいと思います。
申し訳ないですが長いです。

```ShokujiFactory.java
/* 食事Factory */
public abstract class ShokujiFactory {
    public abstract AbstractShushoku   createShushoku();
    public abstract AbstractShirumono  createShirumono();
    public abstract AbstractShusai     createShusai();
    public abstract AbstractFukusai    createFukusai();
}
```
```ChoushokuFactory.java
// 朝食Factory
public class ChoushokuFactory extends ShokujiFactory {
    public AbstractShushoku createShushoku(){
        return new Gohan();
    }
    public AbstractShirumono createShirumono(){
        return new MisoSoup();
    }
    public AbstractShusai createShusai(){
        return new Yakizakana();
    }
    public AbstractFukusai createFukusai(){
        return new Ohitashi();
    }
}
```
```ChuushokuFactory.java
// 昼食Factory
public class ChuushokuFactory extends ShokujiFactory {
    public AbstractShushoku createShushoku(){
        return new Pan();
    }
    public AbstractShirumono createShirumono(){
        return new ConsommeSoup();
    }
    public AbstractShusai createShusai(){
        return new Hamburger();
    }
    public AbstractFukusai createFukusai(){
        return new Salad();
    }
}
```
```YuushokuFactory.java
// 夕食Factory
public class YuushokuFactory extends ShokujiFactory {
    public AbstractShushoku createShushoku(){
        return new Udon();
    }
    public AbstractShirumono createShirumono(){
        return null;
    }
    public AbstractShusai createShusai(){
        return null;
    }
    public AbstractFukusai createFukusai(){
        return null;
    }
}
```
```AbstractShushoku.java
// 主食
public abstract class AbstractShushoku {
    public String toString();
}
```
```Gohan.java
// 御飯
public class Gohan extends AbstractShushoku {
    public String toString() {
        return "御飯";
    }
}
```
```Pan.java
// パン
public class Pan extends AbstractShushoku {
    public String toString() {
        return "パン";
    }
}
```
```Udon.java
// うどん
public class Udon extends AbstractShushoku {
    public String toString() {
        return "うどん";
    }
}
```
```AbstractShirumono.java
// 汁物
public abstract class AbstractShirumono {
    public String toString();
}
```
```MisoSoup.java
//味噌汁
public class MisoSoup extends AbstractShirumono {
    public String toString() {
        return "味噌汁";
    }
}
```
```ConsommeSoup.java
// コンソメスープ
public class ConsommeSoup extends AbstractShirumono {
    public String toString() {
        return "コンソメスープ";
    }
}
```
```AbstractShusai.java
// 主菜
public abstract class AbstractShusai {
    public String toString();
}
```
```Yakizakana.java
// 焼き魚
public class Yakizakana extends AbstractShusai {
    public String toString() {
        return "焼き魚";
    }
}
```
```Hamburger.java
// ハンバーグ
public class Hamburger extends AbstractShusai {
    public String toString() {
        return "ハンバーグ";
    }
}
```
```AbstractFukusai.java
// 副菜
public abstract class AbstractFukusai {
    public String toString();
}
```
```Salad.java
// サラダ
public class Salad extends AbstractFukusai {
    public String toString() {
        return "サラダ";
    }
}
```
```Ohitashi,java
// おひたし
public class Ohitashi extends AbstractFukusai {
    public String toString() {
        return "おひたし";
    }
}
```
```Shokuji.java
// 抽象的な食事クラス
public abstract class Shokuji {
    private AbstractShushoku shushoku;
    private AbstractShirumono shirumono;
    private AbstractShusai shusai;
    private AbstractFukusai fukusai;

    public AbstractShushoku getShushoku() {
        return this.shushoku;
    }
    public void setShushoku(AbstractShushoku shushoku) {
        this.shushoku = shushoku;
    }
    public AbstractShirumono getShirumono() {
        return this.shushoku;
    }
    public void setShirumono(AbstractShirumono shirumono) {
        this.shirumono = shirumono;
    }
    public AbstractShusai getShusai() {
        return this.shusai;
    }
    public void setShusai(AbstractShusai shusai) {
        this.shusai = shusai;
    }
    public AbstractFukusai getFukusai() {
        return this.fukusai;
    }
    public void setFukusai(AbstractFukusai fukusai) {
        this.fukusai = fukusai;
    }

    public abstract void printKondate();
}
```
```Choshoku.java
// 朝食
public class Choshoku extends Shokuji {
    public void printKondate() {
        System.out.println("======== 朝食の献立 ========");
        if (getShushoku() != null) System.out.println("主食: " + getShushoku().toString());
        if (getShirumono() != null) System.out.println("汁物: " + getShirumono().toString());
        if (getShusai() != null) System.out.println("主菜: " + getShusai().toString());
        if (getFukusai() != null) System.out.println("副菜: " + getFukusai().toString());
        System.out.println("===========================");
    }
}
```
```Chuushoku.java
// 昼食
public class Chuushoku extends Shokuji {
    public void printKondate() {
        System.out.println("======== 昼食の献立 ========");
        if (getShushoku() != null) System.out.println("主食: " + getShushoku().toString());
        if (getShirumono() != null) System.out.println("汁物: " + getShirumono().toString());
        if (getShusai() != null) System.out.println("主菜: " + getShusai().toString());
        if (getFukusai() != null) System.out.println("副菜: " + getFukusai().toString());
        System.out.println("===========================");
    }
}
```
```Yuushoku.java
// 夕食
public class Yuushoku extends Shokuji {
    public void printKondate() {
        System.out.println("======== 夕食の献立 ========");
        if (getShushoku() != null) System.out.println("主食: " + getShushoku().toString());
        if (getShirumono() != null) System.out.println("汁物: " + getShirumono().toString());
        if (getShusai() != null) System.out.println("主菜: " + getShusai().toString());
        if (getFukusai() != null) System.out.println("副菜: " + getFukusai().toString());
        System.out.println("===========================");
    }
}
```
```Main.java
public class Main {
    public static void main(String[] args){
        // 朝食生成
        ShokujiFactory factory = new ChoshokuFactory();
        Shokuji choshoku = new Choshoku();
        choshoku.setShushoku(factory.getShushoku());
        choshoku.setShirumono(factory.getShirumono);
        choshoku.setShusai(factory.getShusai());
        choshoku.setFukusai(factory.getFukusai());
        choshoku.printKondate();

        // 昼食生成
        ShokujiFactory factory = new ChuushokuFactory();
        Shokuji chuushoku = new Chuushoku();
        chuushoku.setShushoku(factory.getShushoku());
        chuushoku.setShirumono(factory.getShirumono);
        chuushoku.setShusai(factory.getShusai());
        chuushoku.setFukusai(factory.getFukusai());
        chuushoku.printKondate();

        // 夕食生成
        ShokujiFactory factory = new YuushokuFactory();
        Shokuji yuushoku = new Yuushoku();
        yuushoku.setShushoku(factory.getShushoku());
        yuushoku.setShirumono(factory.getShirumono);
        yuushoku.setShusai(factory.getShusai());
        yuushoku.setFukusai(factory.getFukusai());
        yuushoku.printKondate();
    }
}
```
# 結果
```
======== 朝食の献立 ========
主食: 御飯
汁物: 味噌汁
主菜: 焼き魚
副菜: おひたし
===========================
======== 昼食の献立 ========
主食: パン
汁物: コンソメスープ
主菜: ハンバーグ
副菜: サラダ
===========================
======== 夕食の献立 ========
主食: うどん
===========================
```