現在我們想要將披薩的製作從pizzaFactory放回pizzaStore裡,但又想要保持統一框架與彈性,可以怎麼做呢?就是將create
這個動作變成抽象方法,而生產各自不同口味的pizzaStore就可以繼承它,像這樣...
class PizzaStore
{
public:
Pizza *orderPizza(string type)
{
Pizza *pizza = nullptr;
pizza = createPizza(type);
if(pizza)
{
pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box();
}
return pizza;
};
virtual Pizza* createPizza(string type) = 0;
};
而pizzaStore目前的類別就會這樣呈現...
可以看到orderPizza()
這個方法是在抽象類別─PizzaStore
裡面被定義的,可藉由加上final
的方法來確保它不會被覆寫,這樣就可以保證所有繼承這個PizzaStore
的連鎖店遵循所有相同的order pizza動作;但因為各自要創造出來的口味不同,覆寫的createPizza()
則讓物件的實例由子類別決定。這帶有解耦合的特性,因為對於orderPizza()
而言,它呼叫了createPizza()
,但它不用知道是對哪一種pizza做事。
可以來看看實作各家pizza store的程式碼:
/*程式碼待補*/
而createPizza()
的對象─ pizza,也是由一種抽象類別來組成,create的各式各樣pizza來繼承它:
/*程式碼待補*/
可以來試試看整段程式碼:
/*程式碼待補*/
可以看到目前的架構圖如下:
圖2
可以分成兩大類,被create出來的產品(pizza)與create它的類別(PizzaStore)。可以看到這個架構把pizza
跟PizzaStore
中架構封裝起來,並把create不同種類的的這件事放在各自披薩店的內容中。
已經了解了整個工廠方法的架構,我們來看它的定義─
工廠方法模式定義了一個創建物件的介面,但是讓子類別決定想要實例化哪一個類別。工廠方法可以讓一個類別將實例化的動作推遲到子類別。
看起來有點拗口,可以對照架構圖與這個定義。
圖3
來比較一下跟昨天簡單工廠的區別。
接下來,我們要迎接第六個原則,與工廠系列的另外一個模式─ 抽象工廠。