[問題] 為什麼工廠方法模式的實作要用繼承的?
O'Relly的head first design patterns有些例子不錯,
但Factory Method這邊我看不太懂意義在哪....
想麻煩大家解答一下︰
書上一開始從Simple Factory模式著手,接著用現成的案例延伸到工廠方法模式。
首先他們用pizza類比為工廠產品,PizzaShop負責丟出產品生產與加工後的結果
而SimpleFactory則作為PizzaShop類別的建構子參數,簡單說就是這樣︰
public PizzaShop(SimpleFactory simpleFactory){
this.simpleFactory = simpleFactory; }
public Pizza orderPizza(){
Pizza pizza = simpleFactory.createPizza();
//以上是物件的生產過程 以下是處理物件的SOP流程
pizza.bake();
pizza.box();
return pizza;
}
到這邊我都明白這樣做的用意︰
產生物件與處理物件的SOP流程應該要分開,這樣才不會改一項就動到整個類別。
可是當這例子延伸到工廠方法模式之後,我就不明白為什麼要定義抽象方法?
工廠模式下,PizzaShop變成抽象類別
public Pizza orderPizza(){
Pizza pizza = createPizza();
//內容和上個例子相同 故省略
}
public abstract Pizza createPizza(){
//交給次類別實作
}
書上在這邊是說,PizzaShop類別不需要了解次類別的實作方式就能取得物件。
因此,當產生物件的工廠有好幾種時,就不用像簡單工廠模式那樣,
需要產生多種參數不同的建構式給不同的工廠類別。
選擇實作createPizza次類別的同時,也就決定了產生物件的工廠種類。
但我的問題是,PizzaShop類別可以透過泛型,統一所有工廠類別的呼叫方法,
那為什麼要在PizzaShop設計抽象方法呢?
例如︰
public class PizzaFactory{
public Pizza createPizza(){
//繼承後可覆寫的內容,或是createPizza直接設計為抽象類別
}
}
public class PizzaShop<F extends PizzaFactory>{
private F factory;
public PizzaShop(F factory){ this.factory = factory; } //建構式
public Pizza orderPizza(){
Pizza pizza = factory.createPizza();
//下略 一樣是處理pizza的SOP流程
}
}
寫成這樣,可以同時搞定簡單工廠模式的目地--生產與加工分離,
而且還能彈性地決定生產物件的工廠種類--也就是工廠方法模式想達到的目地,
同時還可以讓物件工廠彼此的生產過程都能有些不同,不需限制細節。
因此我不明白工廠方法模式搞到這麼複雜的意義在哪裡....?
他們到底是想鬆綁哪些物件之間的依賴關係啊?
工廠方法模式的精髓是在哪裡呢?
還是說,這個模式的發展背景是在Java還沒有泛型的年代,
他們只好用這個模式來解決問題?
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.231.147.11
→
08/29 03:58, , 1F
08/29 03:58, 1F
推
08/29 07:02, , 2F
08/29 07:02, 2F
推
08/29 07:19, , 3F
08/29 07:19, 3F
沒事,我只是不太熟泛型罷了.... 給人貼上interface的基礎定義實在很冏....
最後的例子原先是用泛型內繼承寫的,寫了以後,想說看能不能增加工廠類別
實作上的彈性,於是直覺地以為可以限制泛型裡填入的類別都實作特定介面
供orderPizza()呼叫就好,而不必非得要繼承自某個物件....
結果我卻忘記泛型裡面不能implements interface,現在我改回原本構想的樣子。
只是改了以後的物件操作方式就和工廠方法模式類似了....
→
08/29 12:00, , 4F
08/29 12:00, 4F
哈,是沒錯啦,泛型沒有比抽象方法單純....而且潛藏一些初始化過程不當使用的危險
不過原本例子改回當初構想的樣子之後,用哪種方法都沒有什麼本質上的差別。
我想應該就可以不用再討論用哪種方法實作工廠方法比較好囉....
※ 編輯: dream1124 來自: 61.228.46.154 (08/29 12:08)
→
08/29 12:11, , 5F
08/29 12:11, 5F
→
08/29 12:59, , 6F
08/29 12:59, 6F