在java中我们是通过new来实例化一个对象的,但这似乎和面向对象程序设计的一个原则(针对超类型编程,不针对具体实现编程)相悖。因为每当我们用new时就必然会针对具体类,为了解决这个问题就有了一个新的设计模式——工厂模式。 与别的模式不同工厂模式包括三种——简单工厂模式、工厂方法模式、抽象工厂模式。此篇介绍简单工厂模式。
简单工厂模式
严格来说,简单工厂不算一个设计模式,反而比较像是一种编程习惯。姑且就把当一个模式来学习吧。简单工厂模式主要是用来避免直接在客户代码中实例化具体对象以达到提高抽象层次避免针对具体编程的目的。
UML类图
图1
分析:1>Client代表客户代码,就是我们需要一个具体产品的地方,如果不用工厂模式我们可能会直接在此处new一个具体产品出来,然而通过简单工厂模式我们把创建具体产品的职责委托给了简单工厂类,简单工厂类中一般会有一个static的方法专门用来处理创建对象的任务。Product是我们抽取出来的一个抽象类,由它派生出具体产品。这样做的好处也是为了针对接口编程。
2>这看起来似乎只是将创建对象的代码从一个类中转移到了另一个类中,这么做有什么好处呢?
a.重复利用。创建对象的代码可能以后需要在许多类中用到,就上图而言我们可能有多个client
b.封装变化。创建对象的代码最有可能是以后要不断变化的,因为我们可能会增加新的具体产品类,因此我们有必要将这部分代码封装起来,避免影响其它不大会改变的代码。
c.避免在客户代码中出现具体实例化过程。这样做也是为了增强应对未来变化的能力
实例
有一个PizzaStore类,此类用来接受用户的订单并负责加工pizza,有一个SimplePizzaFactory类专职用来创建pizze对象,还有一个抽象pizza类,几个具体pizza类。此例uml类图与定义中的uml类图对应,不再提供此例uml类图。关键代码如下:
1>Pizza
public abstract class Pizza { String pizzaName; public String getPizzaName() { return pizzaName; } void prepare() { System.out.println(pizzaName + ":preparing"); } public void bake() { System.out.println(pizzaName + ":baking"); } public void cut() { System.out.println(pizzaName + ":cutting"); } public void box() { System.out.println(pizzaName + ":boxxing"); } }
2>PizzaStore
public class PizzaStore { public Pizza orderPizza(String pizzaType) { Pizza pizza; // 实例化代码可能在未来发生变化,所以我们交给工厂,避免实例化具体对象 pizza = SimplePizzaFactory.createPizza(pizzaType); // 下面的代码是不大会变化的部分 pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } }
3> SimplePizzaFactory
public class SimplePizzaFactory { public static Pizza createPizza(String pizzaType) { Pizza pizza = null; if (pizzaType.equals("PizzaA")) { pizza = new ConcretePizzaA("APizza"); } else if (pizzaType.equals("PizzaA")) { pizza = new ConcretePizzaB("BPizza"); } else { pizza = new ConcretePizzaA(" Default Pizza"); } return pizza; } }
4>具体pizza类
public class ConcretePizzaA extends Pizza { public ConcretePizzaA(String pizzaName) { super.pizzaName = pizzaName; } } public class ConcretePizzaB extends Pizza { public ConcretePizzaB(String pizzaName) { super.pizzaName = pizzaName; } }
5>测试类
import org.junit.Test; public class TestFactory { @Test public void test() { PizzaStore store = new PizzaStore(); store.orderPizza("PizzaA"); } }
测试结果:
总结:
参考
《Head First Design Pattern》,百度百科。