簡介
根據《head first 設計模式》所述,工廠模式共有三種:簡單/靜態工廠、工廠方法和抽象工廠。
注:其實靜態工廠不是一個設計模式,它更像是一種編程習慣。但是這里是根據[1]所做的筆記,為了方便管理區分,假稱它是工廠模式的一種。
本文介紹靜態工廠方法。
1、定義:利用靜態方法定義一個簡單的工廠,是靜態工廠。
2、原因:使用靜態工廠模式,是因為不需要使用創建對象的方法來實例化對象,因此可以使用靜態方法來創建一個簡單的工廠。
3、缺點:
· 不能通過繼承來改變創建對象的行為。
· 類如果不含有公有的或者受保護的構造方法,就不能被繼承。
4、優點:
·通常來說,想要獲取實例最常用的方法是被調用類提供一個公有的構造方法,但是使用靜態工廠方法會有更好地彈性,當實現方法改變的時候,只需要更改靜態工廠方法就可以了。
· 和構造方法不一樣,靜態工廠方法可以有自己明確的名字。
· 不必每次調用時都創建一個新對象。使用靜態工廠方法對外提供單例,就是事先准備好一個實例,然后多次調用即可,這樣可以減少重復創建實例,不好的地方是需要注意線程安全問題。
· 可以返回原返回類型的任何子類的對象。
5、具體實現(完整代碼):
- 靜態工廠:處理創建對象的細節
public class SimplePizzaFactory{ public Pizza createPizza(String type){ Pizza pizza = null; if(type.equals("cheese")){ return new CheesePizza(); }else if(type.equals("pepperoni")){ return new PepperoniPizza(); }else if(type.equals("clam")){ return new ClamPizza(); }else if(type.equals("veggie")){ return new VeggiePizza(); }else return null; } }
- 客戶端:用來使用靜態工廠來創建對象
public class PizzaStore{ SimplePizzaFactory factory; public PizzaStore(SimplePizzaFactory factory){ this.factory = factory; } public Pizza orderPizza(String type){ Pizza pizza; pizza = factory.createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } }
- 抽象產品類:
public abstract class Pizza { String name;//名稱 String dough;//面團類型 String sauce;//醬料類型 ArrayList<String> toppings = new ArrayList<String>();//一套佐料 void prepare(){ System.out.println("Preparing " + name); System.out.println("Tossing dough..."); System.out.println("Adding sauce... "); System.out.println("Adding toppings: "); for(int i = 0; i < toppings.size(); i++){ System.out.println(" " + toppings.get(i)); } } void bake(){ System.out.println("Bake for 25 minutes at 350"); } void cut(){ System.out.println("Cutting the pizza into diagonal slices"); } void box(){ System.out.println("Place pizza in official PizzaStore box"); } public String getName(){ return name; } public String toString(){ StringBuffer display = new StringBuffer(); display.append("------" + name + "-----\n"); display.append(dough + "\n"); display.append(sauce + "\n"); for(String topping : toppings){ display.append(topping + "\n"); } return display.toString(); } }
- 具體產品類:
//芝士披薩 public class CheesePizza extends Pizza{ public CheesePizza(){ name = "Cheese Pizza"; dough = "Cheese Dough"; sauce = "CheeseSauce"; toppings.add("Cheese Cheese"); } } //蛤蜊披薩 public class ClamPizza extends Pizza{ public ClamPizza(){ name = "Clam Pizza"; dough = "Clam Dough"; sauce = "Clam Sauce"; toppings.add("Clam"); } } //意式臘腸披薩 public class PepperoniPizza extends Pizza{ public PepperoniPizza(){ name = "Pepperoni Pizza"; dough = "Pepperoni Dough"; sauce = "Pepperoni Sauce"; toppings.add("Pepperoni"); } } //素食披薩 public class VeggiePizza extends Pizza{ public VeggiePizza(){ name = "Veggie Pizza"; dough = "Veggie Dough"; sauce = "Veggie Sauce"; toppings.add("Veggie"); } }
- 測試:
public class PizzaTest{ public static void main(String[] args){ SimplePizzaFactory factory = new SimplePizzaFactory(); PizzaStore store = new PizzaStore(factory); Pizza pizza = store.orderPizza("cheese"); System.out.println("Ethan ordered a " + pizza.getName() + "\n"); System.out.println(pizza); pizza = store.orderPizza("veggie"); System.out.println("Joel ordered a " + pizza.getName() + '\n'); System.out.println(pizza); } }
運行結果如下圖所示:
參考資料:
[1] head first 設計模式