查阅不少关于工厂方法模式的介绍,http://luchar.javaeye.com/blog/179616 的文章对我的理解最为深刻,为了加深理解,加入了一些自己的理解并使用自己的代码例子来说明:
工厂模式是负责将大量拥有共同接口的类实例化,而且不必事先知道每次是要实例化哪一个类的模式。
为了更好的理解工厂方法,先简单说明一下简单工厂模式,简单工厂模式就是由一个工厂类根据参数来决定创建出哪一种产品。
抽象产品类
- public interface AbstractProduct {
- public void doSomething();
- }
具体产品类A
- public class ProductA implements AbstractProduct {
- public ProductA() {
- // TODO Auto-generated method stub
- System.out.println("Create ProductA");
- }
- public void doSomething() {
- System.out.println("ProductA do something ...");
- }
- }
具体产品类B
- public class ProductB implements AbstractProduct {
- public ProductB() {
- // TODO Auto-generated method stub
- System.out.println("Create ProductB");
- }
- public void doSomething() {
- System.out.println("ProductB do something ...");
- }
- }
简单工厂类
- public class SimpleFactory {
- public static AbstractProduct createProduct(char catlog) throws Exception {
- switch (catlog) {
- case 'A':
- return new ProductA();
- case 'B':
- return new ProductB();
- default:
- throw new Exception("no product!");
- }
- }
- }
客户端应用
- public class FactotyDemo2 {
- public static void main(String[] args) {
- try {
- AbstractProduct ap = SimpleFactory.createProduct('B');
- ap.doSomething();
- } catch (Exception e) {
- }
- }
- }
简单工厂模式的最大优点在于核心类包含了必要的判断逻辑,可以根据客户的需求动态生成客户所需要的产品,而在客户方面,免除了客户对具体产品创建的依赖,一句话:简单工场实现了对责任的分割,但缺点也很明显,如果需要新增产品C,那么除了新增具体产品C来实现抽象产品接口外,还需要修改工厂类,违背了开放封闭原则中避免直接修改类而是应当通过继承来扩展类的功能的要求,要解决这个问题可重点了解下面的工厂方法模式。
一 、工厂方法(Factory Method)模式
工厂方法模式的核心是一个抽象工厂类,允许很多具体工厂类从抽象工厂类中将创建行为继承下来,也就是说将创建工作延迟到子类去实现,抽象工厂类不再负责产品的创建,仅负责具体工厂类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂类的情况下引进新的产品。
工厂方法(Factory Method)模式,又称多态性工厂(Polymorphic Factory)模式或虚拟构造子(Virtual Constructor)模式;
二、工厂方法模式角色与结构
抽象工厂(Creator)角色:是工厂方法模式的核心,与应用程序无关,任何在模式中创建的对象的工厂类必须实现这个接口。
具体工厂(Concrete Creator)角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。
抽象产品(Product)角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
具体产品(Concrete Product)角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。
三、创建过程如下
一个工厂创建一个产品,所有的具体工厂继承自一个抽象工厂接口。
客户端先创建不同产品的工厂,再由工厂创建具体产品,产品的创建逻辑分散在每个具体工厂类中。
客户端只依赖于抽象工厂与抽象产品,不依赖任何具体的工厂与具体产品
增加新产品时,需要增加具体工厂类和具体产品类,符合OCP原则
四、简单实例
- //抽象产品类
- public interface AbstractProduct {
- public void doSomething();
- }
- //具体产品类A
- public class ProductA implements AbstractProduct {
- public ProductA() {
- // TODO Auto-generated method stub
- System.out.println("Create ProductA");
- }
- public void doSomething() {
- System.out.println("ProductA do something ...");
- }
- }
- //具体产品类B
- public class ProductB implements AbstractProduct {
- public ProductB() {
- // TODO Auto-generated method stub
- System.out.println("Create ProductB");
- }
- public void doSomething() {
- System.out.println("ProductB do something ...");
- }
- }
- //抽象工厂类
- public interface AbstractFactory {
- public AbstractProduct createProduct();
- }
- //具体工厂类A
- public class FactoryA implements AbstractFactory {
- public AbstractProduct createProduct() {
- // TODO Auto-generated method stub
- return new ProductA();
- }
- }
- //具体工厂类B
- public class FactoryB implements AbstractFactory {
- public AbstractProduct createProduct() {
- // TODO Auto-generated method stub
- return new ProductB();
- }
- }
- //客户端工厂应用
- public class FactoryDemo {
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- AbstractFactory af = new FactoryB();
- AbstractProduct ap = af.createProduct();
- ap.doSomething();
- }
- }
五、工厂方法模式与简单工厂模式
工厂方法模式与简单工厂模式再结构上的不同不是很明显。工厂方法类的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。
工厂方法模式之所以有一个别名叫多态性工厂模式是因为具体工厂类都有共同的接口,或者有共同的抽象父类。
当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好的符合了"开放-封闭"原则。而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。
注:我们可以看到,工厂方法中客户端需要决定实例化哪一个工厂来生产自己所需要的产品,判断逻辑仍然存在,仅仅是从简单工厂的内部逻辑判断移到了客户端代码进行逻辑判断。也就是说如果你要想最终生产出ProductC仍然需要修改代码,而只是这次修改的位置移到了客户端!因此,比较好的解决办法是利用反射机制或Ioc原理用配置文件替代工厂类选择的逻辑判断,这里就不论述了。