《Head first设计模式》中使用比萨做例子,我们这里也都用比萨举例。我们假设要开一家比萨店。
工厂模式产生的压力主要来自于增加更多类型的比萨类。同时避免直接实例化对象,因为我们设计程序时应该面向接口编程。这样会让程序更容易维护和扩展,使其更有弹性。
定义:工厂方法方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
遵守的原则:依赖倒置原则,就是要依赖抽象,不要依赖具体类。这个原则比“针对接口编程”更加“抽象”。这个原则说明了:不能让高层组件依赖低层组件,而且,不管高层组件或低层组件,“两者”都应该依赖于抽象。其中的关系,如下图所示:
现在通过结合程序来解释工厂模式。我们需要两个工厂,一个是比萨工厂,另一个是原料工厂。之间的类图关系如下:
根据类图分析程序:
一、首先我们需要有三个抽象,Pizza、PizzaStore、PizzaIngredientFactory,它们分别代表比萨、比萨工厂、原料工厂。代码如下:
* * 从一个抽象比萨开始,所有的具体比萨都必须派生自这个类。 */ public abstract class Pizza { String name; //每一个比萨都持有一组在准备时会用到的原料 Dough dough; Sauce sauce; Veggies veggies[]; Cheese cheese; Pepperoni pepperoni; Clams clam; /** * 把prepare()方法声明成抽象。在这个方法中,我们需要收集比萨所需的原料, * 而这些原料当然是来自原料工厂了。 */ abstract void prepare(); public void bake() { System.out.println("baking"); } public void cut() { System.out.println("cutting"); } public void box() { System.out.println("box"); } public void setName(String name) { this.name=name; } public String getName() { return name; } } * * PizzaStore作为超类,让每个域类型(NYPizzaStore)都继承这个 * PizzaStore,每个子类各自决定如何制造比萨。 */ public abstract class PizzaStore { /** * 每个子类都必须自己实现createPizza方法 * @param type * @return */ protected abstract Pizza createPizza(MenuList type); } public interface PizzaIngredientFactory { /** * 在接口中,每个原料都有一个对应的方法创建该原料。 *这里的每一个原料都是一个类。 */ public Dough createDough(); public Sauce createSauce(); public Cheese createCheese(); public Veggies[] createVeggies(); public Pepperoni createPepperoni(); public Clams createClam(); }
public class ClamPizza extends Pizza { PizzaIngredientFactory ingredientFactory; public ClamPizza(PizzaIngredientFactory ingredientFactory) { this.ingredientFactory=ingredientFactory; } public void prepare() { System.out.println("Preparing "+name); dough=ingredientFactory.createDough(); sauce=ingredientFactory.createSauce(); cheese=ingredientFactory.createCheese(); clam=ingredientFactory.createClam(); } } public class NYPizzaStore extends PizzaStore { public Pizza createPizza(MenuList item) { Pizza pizza=null; //纽约店会用纽约比萨原料工厂的原料 PizzaIngredientFactory ingredientFactory=new NYPizzaIngredientFactory(); if(item==MenuList.Cheese) { pizza=new CheesePizza(ingredientFactory);//把工厂传递给每一个比萨,以便比萨能从工厂中取得原料 pizza.setName("New York Style Cheese Pizza"); }else if(item==MenuList.Veggie) { pizza=new VeggiePizza(ingredientFactory); pizza.setName("New York Style Veggie Pizza"); }else if(item==MenuList.Clam) { pizza=new ClamPizza(ingredientFactory); pizza.setName("New York Style Clam Pizza"); }else if(item==MenuList.Pepperoni) { pizza=new PepperoniPizza(ingredientFactory); pizza.setName("New York Style Pepperoni Pizza"); } if(pizza!=null) { System.out.println(pizza.getName()); } return pizza; } } * * 具体原料工厂必须实现这个接口。 */ public class NYPizzaIngredientFactory implements PizzaIngredientFactory { /** * 为原料家族中的每一种原料都提供了纽约版本 */ public Dough createDough() { return new ThinCrustDough(); } public Sauce createSauce() { return new MarinaraSauce(); } public Cheese createCheese() { return new ReggianoCheese(); } public Veggies[] createVeggies() { Veggies veggies[]={new Garlic(),new Onion(),new Mushroom(),new RedPepper()}; return veggies; } public Pepperoni createPepperoni() { return new SlicedPepperoni(); } public Clams createClam() { return new FreshClams(); } }
public static void main(String[] args) { PizzaStore nyStore=new NYPizzaStore(); Pizza pizza=nyStore.createPizza(MenuList.Cheese); Pizza pizzaVeggie=nyStore.createPizza(MenuList.Veggie); }