这里主要谈论其中的工厂方法模式和抽象工厂模式。
一、定义
工厂方法模式(Factory Method Pattern)定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
抽象工厂模式(Abstract Factory Pattern)提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
二、类图
工厂方法:
抽象工厂:
三、开比萨店
工厂方法:
//Creator public abstract class PizzaStore { //anOperation public Pizza orderPizza(String type){ Pizza pizza; pizza=createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } //factoryMethod abstract Pizza createPizza(String type); } //ConcreteCreator public class NYPizzaStore extends PizzaStore{ Pizza createPizza(String item){ if(item.equals("cheese")){ return new NYStyleCheesePizza(); }else if(item.equals("veggie")){ return new NYStyleVeggiePizza(); }else if(item.equals("clam")){ return new NYStyleClamPizza(); }else if(item.equals("pepperoni")){ return new NYStylePepperoniPizza(); }else return null; } } //Product public abstract class Pizza { String name; String dough; String sauce; ArrayList toppings=new ArrayList(); 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; } } //ConcreteProduct 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"); } }
抽象工厂:
//AbstractFactory public interface PizzaIngredientFactory { //CreateProductA public Dough createDough(); //CreateProductB public Sauce createSauce(); //CreateProductC public Cheese createCheese(); public Veggies[] createVeggies(); public Pepperoni createPepperoni(); public Clams createClam(); } //ConcreteFactory 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 abstract class Pizza { String name; String dough; String sauce; Veggies veggies[]; Cheese cheese; Pepperoni pepperoni; Clams clam; abstract void prepare(); 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"); } void setName(String name){ this.name=name; } public String getName(){ return name; } } //芝士比萨 public class CheesePizza extends Pizza{ PizzaIngredientFactory ingredientFactory; public CheesePizza(PizzaIngredientFactory ingredientFactory){ this.ingredientFactory=ingredientFactory; } void prepare(){ System.out.println("Prepareing "+name); dough=ingredientFactory.createDough(); sauce=ingredientFactory.createSauce(); cheese=ingredientFactory.createCheese(); } } //蛤蜊比萨 public class ClamPizza extends Pizza{ PizzaIngredientFactory ingredientFactory; public ClamPizza(PizzaIngredientFactory ingredientFactory){ this.ingredientFactory=ingredientFactory; } void prepare(){ System.out.println("Prepareing "+name); dough=ingredientFactory.createDough(); sauce=ingredientFactory.createSauce(); cheese=ingredientFactory.createCheese(); clam=ingredientFactory.createClam(); } } public class NYPizzaStore extends PizzaStore{ Pizza createPizza(String item){ Pizza pizza=null; PizzaIngredientFactory ingredientFactory=new NYPizzaIngredientFactory(); if(item.equals("cheese")){ pizza=new CheesePizza(ingredientFactory); pizza.setName("New York Style Cheese Pizza"); }else if(item.equals("veggie")){ pizza=new VeggiePizza(ingredientFactory); pizza.setName("New York Style Veggie Pizza"); }else if(item.equals("clam")){ pizza=new ClamPizza(ingredientFactory); pizza.setName("New York Style Clam Pizza"); }else if(item.equals("pepperoni")){ pizza=new PepperoniPizza(ingredientFactory); pizza.setName("New York Style Pepperoni Pizza"); } return pizza; } }
四、适用性
工厂方法:
1、当一个类不知道它所必须创建的对象的类的时候。
2、当一个类希望由它的子类来指定它所创建的对象的时候。
3、当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
抽象工厂:
1、一个系统要独立于它的产品的创建、组合和表示时。
2、一个系统要由多个产品系列中的一个来配置时。
3、当你要强调一系列相关的产品对象的设计以便进行联合使用时。
4、当你提供一个产品类库,而只想显示它们的接口而不是实现时。
五、要点
1、所有的工厂都是用来封装对象的创建。
2、简单工厂,虽然不是真正的设计模式,但仍不失为一个简单的方法,可以将客户程序从具体类解耦。
3、工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象。
4、抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中。
5、所有工厂模式都通过减少应用程序和具体类之间的依赖促进松耦合。
6、工厂方法允许类将实例化延迟到子类进行。
7、抽象工厂创建相关的对象家族,而不需要依赖它们的具体类。
8、依赖倒置原则,指导我们避免依赖具体类型,而要尽量依赖抽象。
9、工厂是很有威力的技巧,帮助我们针对抽象编程,而不要针对具体类编程。