还是利用比萨店的例子,我们来看看一般工厂模式:
如果比萨店有许多加盟店,并且这些加盟店必须严格按照总部的要求生产比萨。
比如烘烤、切片、打包的方式。但允许加盟店根据各地的特色制作比萨。这要如何实现?
我们可以定义一个抽象类PizzaStore,这个类中有两个方法
orderPizza和createPizza,其中createPizza是抽象的。由子类来具体实现。
在orderPizza方法中定义比萨店的框架。
package com.headfirst.chapter4; public abstract class PizzaStore { public Pizza orderPizza(String type){ Pizza pizza; pizza = createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } abstract Pizza createPizza(String type);//工厂方法 }
纽约和芝加哥的PizzaStore继承这个抽象类
package com.headfirst.chapter4; public class NYStylePizzaStore extends PizzaStore { Pizza createPizza(String type) { Pizza pizza = null; if(type.equals("cheese")){ pizza = new NYStyleCheesePizza(); }else if(type.equals("pepperoni")){ pizza = new NYStylePepperoniPizza(); } return pizza; } }
package com.headfirst.chapter4; public class ChicagoStylePizzaStore extends PizzaStore{ Pizza createPizza(String type) { Pizza pizza = null; if(type.equals("cheese")){ pizza = new ChicagoStyleCheesePizza(); }else if(type.equals("pepperoni")){ pizza = new ChicagoStylePepperoniPizza(); } return pizza; } }
在这两个子类中依据传入参数的类型来决定具体需要生产的比萨。
同样:Pizza类也定义为抽象的
package com.headfirst.chapter4; import java.util.ArrayList; import java.util.List; public abstract class Pizza { String name; String dough; String sauce; List topping = new ArrayList(); void prepare(){ System.out.println("Preparing "+name); System.out.println("Tossing dough..."); System.out.println("Adding sauce..."); for (int i = 0; i < topping.size(); i++) { System.out.println(""+topping.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 offical PizzaStore box"); System.out.println(); } public String getName(){ return name; } }
以下为各城市加盟店具体生产的比萨
package com.headfirst.chapter4; public class NYStyleCheesePizza extends Pizza { public NYStyleCheesePizza() { name = "NY Style Sauce and Cheese Pizza"; dough = "Thin Crust Dough"; sauce = "Marinara Sauce"; topping.add("Grated Reggiano Cheese"); } }
package com.headfirst.chapter4; public class NYStylePepperoniPizza extends Pizza { public NYStylePepperoniPizza() { name = "NY Styel Pepperon Pizza"; dough ="NY Styel pepperon dough"; sauce = "pepperon sauce"; topping.add("pepperon topping"); } }
package com.headfirst.chapter4; public class ChicagoStyleCheesePizza extends Pizza{ public ChicagoStyleCheesePizza() { name = "Chicago Style Deep Dish Cheese Pizza"; dough = "Extra Thick Crust Dough"; sauce = "Plum Tomato Sauce"; topping.add("Shredded Mozzarella Cheese"); } void cut() { System.out.println("Cutting the pizza into square slice"); } }
package com.headfirst.chapter4; public class ChicagoStylePepperoniPizza extends Pizza { public ChicagoStylePepperoniPizza() { name = "Chicago Style Pepperoni Pizza"; dough = "Chicago Style Pepperoni dough"; sauce = "Chicago Style Pepperoni sauce"; topping.add("Chicago Style topping"); } }
最后写一个测试类:
package com.headfirst.chapter4; public class PizzaTestDrive { public static void main(String[] args) { PizzaStore nyPizzaStore = new NYStylePizzaStore(); PizzaStore chicagoPizzaStore = new ChicagoStylePizzaStore(); nyPizzaStore.orderPizza("cheese"); chicagoPizzaStore.orderPizza("cheese"); } }
所有的工厂模式都用来封闭对象的创建,工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封闭的目的。
定义工厂方法模式:
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的是哪一个。工厂方法让类把实例化推迟到子类。
上图中的Creator是一个类,它实现了所有操纵产品的方法 ,但不实现工厂方法
Creator所有的子类都必须实现这个抽象的factoryMethod()方法。
ConcreteCreator实现了factoryMethod()方法以制造实现产品。
简单工厂与工厂方法的差异:
简单工厂把全部的事情在一个地方都处理完了,而工厂方法却是创建一个框架,让子类决定要如何实现。
使用工厂方法有什么好处?
1,避免代码重复
2,方便后期维护
3,针对接口编程,使代码更有弹性,方便未来扩展。