定义:工厂模式是我们最常用的实例化对象的模式,是用工厂方法代替new操作的一种模式,在使用new创建对象时就得考虑,是不是应该用工厂模式来创建对象。用来封装对象的创建,使得代码与对象的创建分离,便于系统的扩展和维护(尽量少的修改量)。工厂模式有简单工厂模式、工厂方法模式和抽象工厂模式。
1 简单工厂模式
简单工厂,虽然不是真正的设计模式,但仍不失为一个简单的方法,可以将客户程序从具体类解耦。通常有个简单工厂类,提供一个静态方法,用来创建所需对象。例如创建一个Pizza对象的简单工厂类,如下:
package com.wp.design.create.factory.headfirst; public class SimplePizzaFactory { public static Pizza createPizza(String type){ Pizza pizza = null; if(type.equals("cheese")){ //奶酪 pizza = new CheesePizza(); }else if(type.equals("greek")){//希腊 pizza = new GreekPizza(); }else if(type.equals("pepperoni")){//意大利辣味香肠 pizza = new PepperonikPizza(); }else if(type.equals("clam")){//蛤 pizza = new ClamPizza(); }else if(type.equals("veggie")){//素食 pizza = new VeggiePizza(); } return pizza; } }
测试类如下:
package com.wp.design.create.factory.headfirst; public class PizzaStore { private SimplePizzaFactory factory; public PizzaStore(SimplePizzaFactory factory){ this.factory = factory; } public Pizza orderPizza(String type){ Pizza pizza = null; pizza = factory.createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } }
这是一个卖批萨(Pizza)的商店,客户可以通过PizzaStore店中的orderPizza()订单方法来获取一个批萨,此时,批萨的生产交给SimplePizzaFactory工厂创建。
2 工厂方法模式
工厂方法使用继承,把对象的创建委托给子类,让子类实现工厂方法来创建对象。所有工厂模式都是通过减少应用程序和具体类之间的依赖促进松耦合。如果这些不理解,看看下面的例子就可以轻松理解了。
import com.wp.design.create.factory.headfirst.simple.Pizza; public abstract class PizzaStore { public Pizza orderPizza(String type){ Pizza pizza = null; pizza = createPizza(type);//此方法从简单工厂中提取出来 pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } protected abstract Pizza createPizza(String type);//创建pizza的方法是抽象的 }
这是一个抽象PizzaStore类,里面的pizza对象的创建由抽象方法createPizza(String type)创建,不过仅仅是一个抽象方法,并没有具体的实现,而Pizza对象的创建一般由PizzaStore的子类实现,如下所示:
import com.wp.design.create.factory.headfirst.simple.Pizza; public class NYPizzaStore extends PizzaStore{ @Override protected Pizza createPizza(String type) { if(type.equals("cheese")){ //奶酪 return new NYStyleCheesePizza(); }else if(type.equals("pepperoni")){//意大利辣味香肠 return new NYStylePepperonikPizza(); }else if(type.equals("clam")){//蛤 return new NYStyleClamPizza(); }else if(type.equals("veggie")){//素食 return new NYStyleVeggiePizza(); }else{ return null; } } }
新开了一家批萨店NYPizzaStore,只需继承PizzaStore类,就可以出售批萨了(用户通过orderPizza()方法下订单),同时NYPizzaStore实现父类的抽象方法createPizza()来创建Pizza对象。这样做的好处是,如果要新开一家批萨店,只需继承PizzaStore类,实现createPizza()方法即可,重点是该店的批萨有自己的特色,那么自己的特色完全由createPizza()方法实现。那么,这种对象的创建交给子类去实现的模式称为工厂方法模式。
测试如下:
public class PizzaTest { public static void main(String[] args) { PizzaStore nyStore = new NYStylePizzaStore(); PizzaStore chicagoStore = new ChicagoStylePizzaStore(); Pizza pizza = nyStore.orderPizza("cheese"); System.out.println("Ethan ordered a "+pizza.getName()+"\n"); pizza = chicagoStore.orderPizza("cheese"); System.out.println("Joel ordered a "+pizza.getName()); } }
3 抽象工厂模式
抽象工厂使用对象组合,对象的创建被实现在工厂接口所暴露出来的方法中,通常用来创建一组产品或家族对象。使得客户从具体产品解耦(产品的创建),要创建一个产品,客户只需使用一个工厂即可获取,完全不需要实例化任何产品对象。示例如下:
public abstract class PizzaStore { public Pizza orderPizza(String type){ Pizza pizza = null; pizza = createPizza(type);//此方法从简单工厂中提取出来 pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } protected abstract Pizza createPizza(String type);//创建pizza的方法是抽象的 }
public class NYPizzaStore extends PizzaStore{ @Override protected Pizza createPizza(String type) { Pizza pizza = null; PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory(); if(type.equals("cheese")){ //奶酪 pizza = new CheesePizza(ingredientFactory); }if(type.equals("clam")){//蛤 pizza = new ClamPizza(ingredientFactory); } return pizza; } }
这是一个工厂方法模式,Pizza对象的创建由子类NYPizzaStore完成。而工厂PizzaIngredientFactory使用的是抽象工厂模式,用来创建批萨的料理对象,代码如下:
public interface PizzaIngredientFactory { public Dough createDough(); public Sauce createSauce(); public Cheese createCheese(); public Veggies[] createVeggies(); public Pepperoni createPepperoni(); public Clams createClams(); }
public class NYPizzaIngredientFactory implements PizzaIngredientFactory { @Override public Dough createDough() { return null; } @Override public Sauce createSauce() { return null; } @Override public Cheese createCheese() { return null; } @Override public Veggies[] createVeggies() { return null; } @Override public Pepperoni createPepperoni() { return null; } @Override public Clams createClams() { return null; } }
NYPizzaIngredientFactory实现抽象工厂接口PizzaIngredientFactory,实现创建具体相关产品。在Pizza的制作过程中即prepare()方法,会用到抽象工厂来获取批萨料理对象。代码如下:
public abstract class Pizza { String name; Dough dough;//面团 Sauce sauce;//酱 Veggies veggies[]; Cheese cheese; Pepperoni pepperoni; Clams clams; 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"); } public String getName(){ return name; } }
public class CheesePizza extends Pizza{ private PizzaIngredientFactory pizzaIngredientFactory; public CheesePizza(PizzaIngredientFactory pizzaIngredientFactory){ this.pizzaIngredientFactory = pizzaIngredientFactory; } @Override void prepare() { System.out.println("Prepare "+name); dough = pizzaIngredientFactory.createDough(); sauce = pizzaIngredientFactory.createSauce(); cheese = pizzaIngredientFactory.createCheese(); } }
一位顾客来到了批萨店,PizzaStore store = new NYPizzaStore();,然后直接store.orderPizza()获取一个批萨便可以用餐了。那么,批萨的获取应用了工厂方法模式,批萨料理对象的获取应用了抽象工厂模式。
4 依赖倒置原则
内容是:要依赖抽象(接口或抽象类),不要依赖具体类。说明:不能让高层组件依赖底层组件,而且高层或底层组件都应该依赖于抽象。上面例子中,PizzaStore是高层组件,Pizza的实现是底层组件,而他们都依赖于Pizza抽象类。
所谓高层组件,是由其他底层组件定义其行为的类。PizzaStore的行为是由Pizza对象定义的,如PizzaStore创建不同的批萨对象,准备、烘烤、切片、装盒,批萨本身属于底层组件。