设计模式之(三)工厂方法模式(Factory Method)
在开发系统中,经常会碰到一个问题。现在需要实现的一些功能,但是这个功能模块以后一定是需要扩展的,那么现在开发中就不仅要实现现在的功能,还要考虑以后的扩展。那么为了系统的健壮,扩展就要遵循开闭原则(简单说,就是对修改关闭,对扩展开发)。
通过场景例子切入工厂方法模式
要实现这个功能,就是要找到一种方法。可以创建一些操作,但是现在不实现,等着以后来实现这个功能。
现在通过一个人成长过程中学到的技能来展示一下这种方案:
在社会中生存技能千千万万,人也是在不断学习技能的,但是都能学习到那些技能自己也不能确定。但是学习技能是一定的。这时候我们就先定义一个技能的类,但是不知道学习的是什么技能,所以就先实现一个技能接口。
package designPattern_3_FactoryMethod; //技能接口 public interface ILifeKills { public void kill(); }
学习的过程不要和技能耦合在一起,需要单独对象来实现,学习的过程就是创建技能对象的过程,所以这个学习对象就是用来生成具体的技能对象的。但是如果是一个人生学习技能方面的框架的话,肯定也不知道学习的是什么技能,那这就是自相矛盾了。怎么办呢?既然是框架,肯定有人来具体实现这个需要学习的技能和具体的学习方式。所以这个我们就知识定义学习方法,但是不定义学习的具体内容,让使用框架的人来实现。这就是定义一个抽象类。
package designPattern_3_FactoryMethod; //抽象学习方法 public abstract class AbstractLearn { public void learn(){ ILifeKills lifekill = factoryMethod();
lifekill.kill(); } protected abstract ILifeKills factoryMethod(); }
下面列出交流、开车的技能
1 package designPattern_3_FactoryMethod; 2 //交流技能 3 public class Talking implements ILifeKills { 4 public void kill(){ 5 System.out.println("交谈技能"); 6 } 7 }
package designPattern_3_FactoryMethod; //开车技术 public class Driver implements ILifeKills { @Override public void kill() { // TODO Auto-generated method stub System.out.println("开车技术!"); } }
具体学习的方法
package designPattern_3_FactoryMethod; //学习交流的对象 public class LearnTalking extends AbstractLearn { public ILifeKills learn(){ return new Talking(); } }
package designPattern_3_FactoryMethod; //学习开车 public class LearnDriver extends AbstractLearn { @Override protected ILifeKills factoryMethod() { // TODO Auto-generated method stub return new Driver(); } }
客户端调用
1 package designPattern_3_FactoryMethod; 2 3 public class Client { 4 5 public static void main(String[] args) { 6 AbstractLearn al = new LearnTalking(); 7 al.learn(); 8 AbstractLearn al2 = new LearnDriver(); 9 al2.learn(); 10 } 11 }
这面展示的例子就是工厂方法模式。只是我只生产一个具体的对象。以后根据需要可以生成对应的技能对象。接下来先看下工厂模式的定义,再结合简单工厂模式分析。结构图
分析工厂方法模式
定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
工厂方法的意义,在父类不知道需要生产具体对象的情况下,能够完成自身的功能调用,具体的实现延迟到其子类,实际上就是工厂类也抽象化了,具体的对象在各自的工厂子类中来实现。
通过定义可以看出:抽象出来具体对象的接口,同时把工厂类也抽象化,这样产品对象和具体工厂都实现各自的抽象类,以后在扩展具体的对象的时候不用修改原来的工厂类,这也更加符合开闭原则。同时也看出来了,工厂方法模式是简单工厂模式的衍生。如果把工厂类的抽象类省略到,用普通类选择实现,那么工厂方法模式就回来到简单工厂模式。
在使用工厂方法的时候要具有灵活性,在一个具体的工厂功法里面可以有多个不同的工厂方法,也可以在一个工厂类中实现十分相近的产品。看着有点类似简单工厂了,但是本质上还是工厂方法的本质。只是形式有些变化而已,但是这不重要。就像学习武功,只要内功深厚,很多招式都能够灵活运用,看似神奇,其实都是内功支撑。而设计模式也是如此。工厂方法模式只要把具体对象的实现延迟到子类,以后扩展工厂时候不用再去修改原来的工厂类,符合了开闭原则。那么就抓住了工厂方法模式的本质。
分析了这么多工厂模式的优点,它当然也有缺点。就是会加大代码的复杂度,如果在不合适的场景中用到很有可能得不偿失。
小结
工厂方法的本质:就是把对象的实现延迟到其子类来实现,使得对产品的扩展更加灵活。这也是工厂方法模式和简单公共的区别。
工厂方法不是不可以选择实现。以我的理解,在一个具体的工厂类中,可以实现相近的产品。以后扩展的时候再派生另外的类就可以了。
下一篇分析抽象工厂模式