1.定义
定义一个创建对象的接口,由子类决定实例化的类是哪一个,工厂方法把类的实例化推迟到子类.
注意:虽然简单工厂模式平常用的很多,但是它更像是一个编程习惯而并不是一个设计模式,工厂模式主要包括工厂模式和抽象工厂模式.
2.代码实现
还是以pizza为例子,上个简单工厂模式中说到了有四种披萨,分别是:芝士披萨,花甲披萨,意式香肠披萨,蔬菜披萨.
假如不同地区生产的pizza不一样,比如有:
纽约芝士披萨,纽约花甲披萨,纽约意式香肠披萨,纽约蔬菜披萨
或者是
芝加哥芝士披萨,芝加哥花甲披萨,芝加哥意式香肠披萨,芝加哥纽约蔬菜披萨.
这些披萨的实现类如下:
定义抽象披萨类
public abstract class Pizza { String name; String dough; String sauce; ArrayList toppings = new ArrayList(); public void prepare() { System.out.println("Prepare:"+name); System.out.println(toppings); } public void bake() { System.out.println("bake:"+name); } public void cut() { System.out.println("cut:"+name); } public void box() { System.out.println("box:"+name); } public String getName() { return name; } }
纽约四种披萨:
public class NYStyleCheesePizza extends Pizza { public NYStyleCheesePizza() { name = "NY Style Sauce and Cheese Pizza"; dough = "Thin Crust Dough"; sauce = "Marinara Sauce"; toppings.add("Grated Reggiano Cheese"); } }
public class NYStyleClamPizza extends Pizza { }
public class NYStylePepperoniPizza extends Pizza { }
public class NYStyleVeggiePizza extends Pizza { }
芝加哥四种披萨:
public class ChicagoStyleCheesePizza extends Pizza { public ChicagoStyleCheesePizza() { name = "Chicago Style Deep and Cheese Pizza"; dough = "Extra Thick Crust Dough"; sauce = "Plum Tomato Sauce"; toppings.add("Shredded Mozzarella Cheese"); } public void cut() { System.out.println("Cutting the pizza into square slices"); } }
public class ChicagoStyleClamPizza extends Pizza { }
public class ChicagoStylePepperoniPizza extends Pizza { }
public class ChicagoStyleVeggiePizza extends Pizza { }
虽然简单工厂可以创建不同的工厂类来生成,但是这些工厂类在传入Store后只能生成一种地区的pizza,如果要生成别的地区的pizza还要重新传入工厂类.
这里我们用改进后的工厂模式实现.
定义抽象披萨商店类,这边和简单工厂模式不同的是定义成了抽象类,因为需要子类来决定具体生产哪一种披萨
public abstract class PizzaStore { public PizzaStore() {} public Pizza orderPizza(String type) { Pizza pizza; pizza = createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } /** * 让子类决定生成哪一种披萨 * @param type 参数类型 * @return 披萨 */ abstract Pizza createPizza(String type); }
定义纽约披萨商店和芝加哥披萨商店
public class NYStylePizzaStore extends PizzaStore { public NYStylePizzaStore() { super(); } @Override Pizza createPizza(String type) { if (type.equals("cheese")) { return new NYStyleCheesePizza(); } else if (type.equals("pepperoni")) { return new NYStylePepperoniPizza(); } else if (type.equals("veggie")) { return new NYStyleVeggiePizza(); } else if (type.equals("clam")) { return new NYStyleClamPizza(); } return null; } }
public class ChicagoStylePizzaStore extends PizzaStore { @Override Pizza createPizza(String type) { if (type.equals("cheese")) { return new ChicagoStyleCheesePizza(); } else if (type.equals("pepperoni")) { return new ChicagoStylePepperoniPizza(); } else if (type.equals("veggie")) { return new ChicagoStyleVeggiePizza(); } else if (type.equals("clam")) { return new ChicagoStyleClamPizza(); } return null; } }
定义测试类并进行测试
public class PizzaTest { public static void main(String[] args) { PizzaStore nyPizzaStore = new NYStylePizzaStore(); PizzaStore chicagoStore = new ChicagoStylePizzaStore(); Pizza pizza = nyPizzaStore.orderPizza("cheese"); System.out.println(); pizza = chicagoStore.orderPizza("cheese"); /* 输出如下: Prepare:NY Style Sauce and Cheese Pizza [Grated Reggiano Cheese] bake:NY Style Sauce and Cheese Pizza cut:NY Style Sauce and Cheese Pizza box:NY Style Sauce and Cheese Pizza Prepare:Chicago Style Deep and Cheese Pizza [Shredded Mozzarella Cheese] bake:Chicago Style Deep and Cheese Pizza Cutting the pizza into square slices box:Chicago Style Deep and Cheese Pizza */ } }
3.总结
可以看到工厂模式最主要的特点就是子类决定生成哪一种披萨,虽然和简单工厂模式有点像,if else 挺多的,但是子类来做决定的话弹性更高一点,而且也更直观理解要生成什么对象.
虽然工厂模式避免不了用new关键字创建类,但是它把类的创建都归并到一起了,便于管理.
反射也可以创建类,spring就是通过反射来实现ioc的.