Factory Method

インスタンスの作り方をスーパークラスで抽象的に定義しておき,その具体的な実装を継承したサブクラスで行う. Factory MethodはTemplate Methodをインスタンス生成に適用したパターンであると考えることができる.

クラス構造

templateパッケージの中に,抽象クラスとして,CookerクラスとDishクラスがある.これらのクラスには,抽象メソッドが含まれるので,これらのクラスを継承するサブクラスでは,抽象メソッドを実装する必要がある.

このような定義によって,スーパークラスでは,共通するメソッドなどの骨組みを作り,それをサブクラスで具体的に実装することができる.これによって,外部から見て,メソッドが共通であるので,メソッドを呼ぶという手続きは同じでありながら,サブクラスで,各々の特徴となる具体的な処理内容を定義することができる.


ソースコード

調理師を意味するCookerクラスは,抽象クラスとして定義されており,「Dish」を返す「cooking」メソッドを持つ.また,「providing」メソッドは,料理を客に出すときの出し方を定義している.「working」メソッドは料理を作って,それを出すという,一連のメソッドを実行する.

package template;
public abstract class Cooker
{
    protected abstract Dish cooking(String order);
    protected abstract void providing(Dish dish);
    public void working(String order){
        Dish dish = cooking(order);
        providing(dish);
    }
}

調理師が生成する料理を抽象クラスとして,Dishクラスを定義する.Dishクラスでは,料理の完了をお知らせするためのメソッド「introduction」メソッドが抽象メソッドとして定義されているため,サブクラスで実装する必要がある.setDishNameとgetDishNameにて,料理の名前を設定,応答する.

package template;
public abstract class Dish{
    private String dishName;
    public String getDishName(){
        return dishName;
    }
    public void setDishName(String order){
        dishName = order;
    }
    protected abstract String introduction();
}

抽象クラスとして,調理師クラスと料理クラスを定義する.これらを継承したサブクラスにて,抽象メソッドを実装することで,抽象的に動作を定義したところに,具体化したクラスがあてはまるようになる.

以下に,寿司職人が寿司を作る場合を想定して実装したクラスを示す.寿司職人は「料理」を返り値とする「調理する」メソッドでは,寿司を作ってそれを返す.返り値の型が「料理」クラスではなく「寿司」クラスであるが,「寿司」クラスは「料理」クラスを継承しているため,スーパークラスで定義されている値と合致しているので,問題ない.

package worker;
import template.Cooker;
import template.Dish;
public class SushiShokunin extends Cooker{
    protected Dish cooking(String order){
        return new Sushi(order);
    }
    protected void providing(Dish dish){
        System.out.println(dish.introduction() + "食ってくんな!");
    }
}

「料理」クラスを継承して「寿司」クラスを作る.

package worker;
import template.Cooker;
import template.Dish;
public class Sushi extends Dish{
    public Sushi(String sushiType)
    {
        setDishName(sushiType);
    }
    protected String introduction(){
        return getDishName() + "一丁!";
    }
}

実装した結果を用いて,実行するプログラムを与える.

import template.Cooker;
import worker.SushiShokunin;
public class Main
{
    public static void main(String args[])
    {
        Cooker sushiShokunin = new SushiShokunin();
        sushiShokunin.working("トロ");
        sushiShokunin.working("マグロ");
    }
}

実行した時の出力結果を以下に示す.

トロ一丁!食ってくんな!
マグロ一丁!食ってくんな!

演習

(1)追加

寿司職人クラスと寿司クラスの場合と同様に,パティシエクラスを追加して,パティシエがつくるケーキクラスを作る. また,Mainクラスにて,パティシエをインスタンス化し,パティシエにケーキ類のオーダーをして,オーダーしたケーキ類が返ってくることを確認する.

(2)FactoryMethod全体を作る

家電を作る工場と,家電を抽象クラスとして定義し,それらを継承して,テレビ工場クラスとテレビクラス,冷蔵庫工場クラスと冷蔵庫を作る. さらに,テレビ工場がテレビを作って出荷する手順,冷蔵庫工場が冷蔵庫を作る手順を試す.

さらに,作成したクラスのクラス図を作成する.

提出

内容:FactoryMethodパターンの作成
締切日時:1月17日17:00
提出先:Blackboard
課題:FactoryMethod パターンの演習「(2)FactoryMethod全体を作る」の課題
   http://teacher.nagano-nct.ac.jp/fujita/FactoryMethod.php
提出物:(1)作成したクラスのソースコード,(2)実行した結果,(3)クラス図 を作成したうえで,(1)-(3)を含むPDFにまとめて提出する.
     (例:875_藤田悠.pdf)

Factory Method