除了使用new操作符之外,還有更多製造物件的方法,比如使用工廠模式封裝例項化的行為。工廠模式在輔助面向介面程式設計時很有作用,它用來封裝物件的建立。
本章從簡單工廠開始講起,並逐步深入了解工廠方法(factory method)和抽象工廠模式(abstract factory),從嚴格意義上來說簡單工廠並不是乙個設計模式,但對理解後兩者有幫助。以pizza店為例子,貫穿整章,pizza店生產各款各式的pizza,有clam、veggie pizza、greek pizza、cheese pizza
pizza orderpizza(string type) else if (type.equals("pepperoni")) else if (type.equals("clam")) else if (type.equals("veggie"))
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
pizza.pizza();
}
上述**看似可以將具體實現與介面分離,但是有個新的問題是當要加入新的pizza品種或移動時就得修改該**,這違背了設計原則----encapsulate what varies,我們得把建立pizza這一塊**封裝起來,於是乎有了簡單工廠的出現
[color=red]一、簡單工廠:[/color]
package headfirst.factory.pizzas;
//簡單工廠類
public class ******pizzafactory else if (type.equals("pepperoni")) else if (type.equals("clam")) else if (type.equals("veggie"))
return pizza;}}
//pizza店
package headfirst.factory.pizzas;
public class pizzastore
public pizza orderpizza(string type)
}
簡單工廠類圖:
[img]
基於以上實現可以滿足生產不同的種類的pizza,如clam蛤蜊比薩)、veggie pizza(素食比薩)、greek pizza(希臘比薩)、cheese pizza(乳酪比薩),但是對於不同的地區,必然有地區口味的差別,如紐約和芝加哥口味,那我們就需要加多兩個生產紐約和芝加哥口味的工廠,而不是用上述的簡單工廠來生產,於是會出現像下面的**
//紐約風味的veggiepizza
nypizzafactory nyfactory = new nypizzafactory();
pizzastore nystore = new pizzastore(nyfactory);
nystore.order("veggie");
//芝加哥風味的veggiepizza
chicagopizzafactory chicagofactory = new chicagopizzafactory ();
pizzastore nystore = new pizzastore(chicagofactory );
nystore.order("veggie");
新的問題又一次出現,pizzastore提供了標準的pizza製作過程,如準備、烘烤、切片、裝箱,但是有些地方可能不切片,或是用他們自己的盒子裝箱,那麼這樣的設計就不能滿足了,它只提供了不能口味的生產,但是使用了統一的加工製作過程。為此,工廠方法factory method出現了
[color=red]二、工廠方法模式(factory method)[/color]
package headfirst.factory.pizzafm;
public abstract class pizzastore
}package headfirst.factory.pizzafm;
public class nypizzastore extends pizzastore else if (item.equals("veggie")) else if (item.equals("clam")) else if (item.equals("pepperoni")) else return null;}}
//與實現了自己的工廠方法的各個工廠類對應的pizza
package headfirst.factory.pizzafm;
public class nystylecheesepizza extends pizza
}package headfirst.factory.pizzafm;
public class pizzatestdrive
}
the factory method pattern:定義了乙個生產物件的介面,但由子類決定生產哪些例項物件
pizza的工廠方法設計模式圖
[img]
工廠方法設計模式圖
[img]
設計原則:
[img]
pizza總公司為了確保每家加盟店使用高質量的原料,打算建造多家生產原料的工廠,為每家分店提供的做比薩餅的原料。於是有
package headfirst.factory.pizzaaf;
//抽象工廠介面,定義了如何生產一組產品的方法
public inte***ce pizzaingredientfactory
//紐約pizza店的原料加工廠
package headfirst.factory.pizzaaf;
//具體工廠
public class nypizzaingredientfactory implements pizzaingredientfactory
public sauce createsauce()
public cheese createcheese()
public veggies createveggies() ;
return veggies;
}public pepperoni createpepperoni()
public clams createclam() }//
package headfirst.factory.pizzaaf;
public class cheesepizza extends pizza
void prepare()
}//pizza店
package headfirst.factory.pizzaaf;
public class nypizzastore extends pizzastore else if (item.equals("veggie")) else if (item.equals("clam")) else if (item.equals("pepperoni"))
return pizza;}}
[color=red]三、抽象工廠模式(abstract factory)[/color]
上述例子中的原料加工廠用的就是抽象工廠的設計模式
抽象工廠模式類圖
[img]
pizza店例子的抽象工廠設計模式圖
[img]
在上圖中,chicagopizzaingredidentfactory依賴於thickcustdough、plumtomatosauce、mozzarella cheese、frozenclams,而pizza類只依賴於原料的介面dough、sauce、cheese、clams,這樣當這些原料的具體類的改動時,只是影響到chicagopizzaingredidentfactory,而pizza類不會受影響,這很好的體現了設計原則:依賴倒置原則.
遵循下列指導方針可避免設計中的違反依賴倒置的原則
1、變數不可以持有具體類的引用
2、不要讓類派生自具體類
3、不要覆蓋基類中已實現的方法
[color=red]總結:[/color]
工廠方法(factory method)vs抽象工廠(abstract factory)的比較
不同點:
1、工廠方法用於生產乙個物件,而抽象工廠用於生成一組相關的物件
2、工廠方法的抽象基類已經使用了子類將要建立的具體物件,而抽象工廠只負責建立,具體建立的物件的使用由裝配了該工廠的類決定。
相同點:
1、同樣都是封裝了物件的建立和保持應用程式的對具體實現的鬆散耦合
《head first》設計模式之四 工廠模式
工廠模式一章講了很多內容,但是設計思想是一致的 1 變數不可以持有具體類的引用 如果使用new 就會持有具體類的引用,可以用工廠類避開 2 不要讓類派生自具體類 如果派生自具體類,那就是依賴具體的實現類,彈性差,請派生自抽象類或者介面 3 不要覆蓋基類中已實現的方法 如果覆蓋基類已實現的方法,那基類...
headfirst設計模式
花了一周多一點的時間看完了headfirst的設計模式。看完之後有一種恍然大悟的感覺,仔細想想有覺得自己好像什麼也看懂。簡單說下對這本書的一點感悟吧,headfirst的書比較通俗易懂,之前看了四人幫的設計模式,看一半就有一種痛不欲生的感覺,自己水平有限,看不懂,也就沒在勉強自己了。對於模式其實簡單...
HeadFirst 設計模式 工廠模式
定義乙個建立物件的介面,由子類決定要例項化的類。工廠方法將類例項推遲到子類。依賴倒置。第一種方式是 class pizzastore public pizza orderpizza string type class pizzafactory pizza pizza null 將pizza這個例項提...