工厂方法
设计原则:依赖倒置原则(要依赖抽象,不要依赖具体类)
该设计原则的最佳实践方式的几个指导方针:
1.变量不可以持有具体类的引用。(如果使用new,就会持有具体类的引用,可用工厂来避开这样的做法)
2.不要类派生自具体类。(如果派生自具体类,就会依赖具体类)
3.不要覆盖基类中已实现的方法。(如果覆盖基类已实现的方法,那么你的基类就不是一个真正适合被继承的抽象,基类中实现的方法应该由所有的子类共享)
我们在写代码的时候尽量去追寻这些方针,将这些方针内化成你的设计的一部分(不追求代码之美的自动忽略)。
下面回到工厂模式
先来看下工厂方法模式的定义:工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
工厂方法的UML图:
下面是Head First中关于工厂方法模式的PizzaDemo:
package com.zjut.json.factoryMethod; import java.util.ArrayList; /** * 披萨类 * * @author json * * @date 2013-5-7 */ public abstract class Pizza { /**pizza的名字*/ private String name; /**pizza的面团类型*/ private String dough; /**pizza酱料类型*/ private String sauce; /**pizza相关佐料*/ @SuppressWarnings("rawtypes") ArrayList toppings = new ArrayList(); public void prepare(){ System.out.println("Preparing " + getName()); System.out.println("Tossing dough..."); System.out.println("Adding sauce..."); System.out.println("Adding toppings: "); for(int i = 0; i < toppings.size(); i++){ if(i == toppings.size()-1){ System.out.print( toppings.get(i)); }else{ System.out.print(toppings.get(i) + ","); } } } public void bake(){ System.out.println("Bake for 25 minutes at 350"); } public void cut(){ System.out.println("Cutting the pizza into diagonal slices"); } public void box(){ System.out.println("Place pizza in official PizzaStore box"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDough() { return dough; } public void setDough(String dough) { this.dough = dough; } public String getSauce() { return sauce; } public void setSauce(String sauce) { this.sauce = sauce; } @SuppressWarnings("rawtypes") public ArrayList getToppings() { return toppings; } @SuppressWarnings("rawtypes") public void setToppings(ArrayList toppings) { this.toppings = toppings; } }
package com.zjut.json.factoryMethod; /** * 具体风味的披萨 * * @author json * * @date 2013-5-7 */ public class NYStyleCheesePizza extends Pizza { @SuppressWarnings("unchecked") public NYStyleCheesePizza(){ setName("NY Style Sauce and cheese Pizza"); setDough("Thin Crust Dough"); getToppings().add("Grated Reggiano Cheese"); } }
package com.zjut.json.factoryMethod; /** * 具体风味的Pizza * * @author json * * @date 2013-5-7 */ public class ChicagoStyleCheesePizza extends Pizza { @SuppressWarnings("unchecked") public ChicagoStyleCheesePizza(){ setName("Chicago Style Sauce and cheese Pizza"); setDough("Extra Thick Crust Dough"); setSauce("Plum Tomato Sauce"); getToppings().add("Shredded Mozzarella Cheese"); } public void cut(){ System.out.println("Cutting the pizza into square slices"); } }
package com.zjut.json.factoryMethod; /** * 披萨商店 * * @author json * * @date 2013-5-7 */ public abstract class PizzaStore { public final Pizza orderPizza(final String type){ Pizza pizza; pizza = createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } /** * 创建pizza的抽象方法 * * @param type pizza的类型那个 * * @return Pizza对象 */ protected abstract Pizza createPizza(final String type); }
package com.zjut.json.factoryMethod; /** * 具体披萨商店 * * @author json * * @date 2013-5-7 */ public class NYPizzaStore extends PizzaStore { @Override protected Pizza createPizza(String type) { if("cheese".equals(type)){ return new NYStyleCheesePizza(); } return null; } }
package com.zjut.json.factoryMethod; /** * 具体披萨商店 * * @author json * * @date 2013-5-7 */ public class ChicagoPizzaStore extends PizzaStore { @Override protected Pizza createPizza(String type) { if("cheese".equals(type)){ return new ChicagoStyleCheesePizza(); } return null; } }
测试类:
package com.zjut.json.factoryMethod; /** * @author json * * @date 2013-5-7 */ public class PizzaStoreTest { public static void main(String[] args){ PizzaStore nystore = new NYPizzaStore(); PizzaStore chicagostore = new ChicagoPizzaStore(); Pizza pizza = nystore.orderPizza("cheese"); System.out.println("Json ordered a " + pizza.getName()); pizza = chicagostore.orderPizza("cheese"); System.out.println("Joe ordered a " + pizza.getName()); } }
测试结果:
收工!!!
人生最可贵的事情是sb似的坚持于追求……