前言创建型模式抽象了实例化过程。它们帮助一个系统独立于如何创建、组合和表示它的那些对象。一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化托给另一个对象。随着系统演化得越来越依赖于对象复合而不是类继承时,创建型模式变得更为重要。接下来,我们马上进入对第一个创建型模式的介绍——工厂方法模式。动机软件系统中,经常面临着“某个对象”的创建问题。由于用户需求的改变,该对象的具体实现时常面临着剧烈的变化,但是其所固有的接口却是比较稳定的,如何来应对这种需求上变化?通过封闭机制来隔离这个“易变对象”的变化点,使系统中“依赖于该对象的对象”不会随着需求的改变而改变,保持系统一定的稳定性和健壮性。这就是工厂方法善于解决的方面呢。意图定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod使一个类实例化延迟到其子类。结构图1.抽象工厂(creator)角色:是工厂方法模式的核心,任何通过该模式创建对象的具体工厂类都须实现该接口2.具体工厂(ConcreteCreator)角色:实现了抽象工厂类的具体工厂类,包含与应用程序相关的逻辑,被客户端调用以生成具体的产品对象。在上图中类BMWCreator和BENZCreator就是两个具体的工厂实现类,用于创建不同实现的Car对象3.抽象产品(Product)角色:工厂方法所创建的对象的父类型,也就是具体产品对象的共同父类或者说是共同拥有的接口。在上图中,这个角色为Car4.具体产品(ConcreteProduct)角色:实现了抽象产品接口的产品。每个具体产品与创建自己的具体工厂是一般来说是一一对应。上图中,BMW和BENZ就是两个具体的具体产品类代码示例1:publicabstractclassCar{2:publicabstractvoidMove();3:publicabstractvoidStop();4:}5:6:publicclassBMWextendsCar{7:publicvoidMove(){8:System.out.println(BMWisMoving!);9:}10:publicvoidStop(){11:System.out.println(BENZisStopping!);12:}13:}14:15:publicclassBENZextendsCar{16:publicvoidMove(){17:System.out.println(BENZisMoving!);18:}19:publicvoidStop(){20:System.out.println(BENZisStopping!);21:}22:}23:24:publicabstractclassCreator{25:publicabstractCarfactory();26:}27:28:publicclassBMWCreatorextendsCreator{29:publicCarfactory(){30:returnnewBMW();31:}32:}33:34:publicclassBENZCreatorextendsCreator{35:publicCarfactory(){36:returnnewBENZ();37:}38:}39:{41:publicstaticvoidmain(String[]args){42:Creatorc1=newBMWCreator();43:Creatorc2=newBENZCreator();44:45:Carbmw=c1.factory();46:Carbenz=c2.factory();47:48:bmw.Move();49:bmw.Stop();50:51:benz.Move();52:benz.Stop();53:}54:}从上面代码中,我们可以很清楚地看到,工厂方法实现的一般做法。从客户端代码上来看,我们均是操作抽象类对象,这也是面向接口编程的核心。需要创建具体产品对象,只需要首先获取对应的产品工厂,再由其创建具体产品对象。在这里,我们可以看到:工厂方法模式实现时,客户端需要决定实例化哪一个具体工厂来创建特定的产品对象,对比简单工厂模式,工厂方法把内部逻辑判断转移到了客户端代码来进行,想要实例化新的产品对象,只需要修改客户端同时添加对应的具体工厂类,而不需要修改工厂类,符合了面向对象的“开闭原则“——对扩展开放,对修改关闭。而简单工厂模式的最大优点在于工厂类方法中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对客户端来说,除去了与具体产品的依赖,但是当添加新的产品时,就不得不修改工厂类逻辑,违背了”开闭原则“。现实场景在实际的运用场景中,工厂方法应该是最被常用的模式之一呢。不仅因为此模式实现过程的简约,更是因为其实用性。应该说,在任何商业软件系统中都不乏工厂方法模式的身影,比如利用工厂方法模式切换各种数据库示例,由于主流的数据库几乎都支持增、删、改、查的功能(即crud),换句话来说就是各数据库所支持的接口都是相同的,但是不同的数据库有不同的实现方式,通过工厂方法模式,我们就可以很方便地动态创建各种接口相同但是实现不同的数据库操作类对象。具体实现的方式与示例代码的实现框架一致,这里就不重复举例呢。实现要点1.FactoryMethod模式有两种方式:一是Creator类是抽象类且它不提供其所声明的工厂方法实现;二是Creator类是一个具体类并提供其所声明的工厂方法的默认实现2.工厂方法的作用不仅仅局限于对象的创建上,同时可以在工厂方法中完成对各种对象或者资源的初始化,各种参数的设置等3.在工厂方法的实现过程中,通常一个特定产品对应一个特定的具体工厂,即所谓的一对一关系。而不管工厂还是产品都是针对统一的接口来编码实现。典型的面向接口编程方式运用效果1.用工厂方法在一个类的内部来创建一个对象通常比直接实例化一个对象更加灵活方便2.FactoryMethod通过面向对象的方法,将对象的创建工作延迟到子类,提供了一种灵活的扩展方式,很好地将产品与客户端原本的紧耦合变成松耦合关系。适应性1.当一个类不知道它所必须创建的对象的类的时候2.当一个类希望由它的子类来指定它所创建的对象的时候3.当类将创建对象的职责委托给多个帮助子类中某一个,并且希望将哪一个帮助子类是代理者这一信息局部化的时候相关模式1.工厂方法模式与抽象工厂方法模式:这两个模式都可以组合使用,详细地说明请参考下一代对抽象工厂方法模式的讲解分析。2.工厂方法模式与模板方法模式:这两者外观类似,都有一个抽象类,然后由子类来提供一些实现,但是工厂方法模式的子类专注的是创建产品对象,而模板方法模式的子类专注的是为固定算法骨架提供某些步骤的具体实现。这两个模式可以组合使用,通过在模式方法模式里,通过工厂方法来创建模板方法所需要的对象。总结工厂方法模式的本质是:延迟到子类来选择实现。工厂方法很好地体现了开闭原则和依赖倒置原则。”开闭原则“告诉我们”对扩展开放,对修改关闭“,在工厂方法模式中,我当我们需要添加新的产品对象时,只需要根据产品接口实现新的产品对象以及根据抽象的工厂方法接口来实现新的具体工厂,然后通过相同的逻辑利用对应的具体的工厂方法来创建该新产品对象。”依赖倒置原则“告诉我们的”要依赖抽象,不要依赖于具体类“,简单地说就是让高层组件依赖于低层组件,而且不管高层组合还是低层组件都应该依赖于抽象,而不是具体的实现,在工厂方法模式中,我们可以看到,不管是具体工厂类还是具体产品类都是根据统一的接口(或者抽象)来完成各种不同实现,而且客户端也只需要与相应的抽象类找交道即可。好呢,工厂方法模式的讲解就到这吧,相较而言,工厂方法模式的实现比较简单,我们大家需要理解的是其本质和适应场景。下一篇,我们将继续介绍工厂方式模式的同胞兄弟——抽象工厂方法模式,敬请期待!前言在上一篇介绍的工厂方法模式,主要用于创建单个对象,但是如果需要在一个工厂方法中创建一系列相关或者相互依赖的对象时,我们是又该如何应对呢?如果完全按照工厂方法模式来设计,那么在设计的过程中,我们必然会面对越来越多的工厂类,但是由于这些对象彼此间存在一定的关联依赖性,我们或许可以通过机制将这一系列对象的创建工作统一封装起来?这就是即将登场的——抽象工厂方法模式擅长之处呢!动机在软件系统中,我们经常面临着一系列相关或者相互依赖的对象的创建工作,又由于需求的多样化,导致在系统的演化过程中,存在越来越多的系列对象的创建工作。这时,常规的对象创建模式已然不能很灵活地处理这种场景,我们需要提供一种更加紧凑的“封装机制”来规避客户程序与这种多系列对象创建工作的紧耦合。这便是抽象工厂方法模式的由来。意图提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类。结构图1.抽象工厂(AbstractFactory)角色:声明一个创建抽象产品对象的操作接口,是抽象工厂方法模式的核心,与业务逻辑无关。2.具体工厂(ConcreteFactory)角色:创建具体产品对象的操作,含有选择适当的产品对象的逻辑,该逻辑与系统的业务逻辑紧密相关。3.抽象产品(AbstractProduct)角色:为一类产品对象声明的一个接口,是工厂方法所创建的对象的父类。4.具体产品(ConcreteProduct)角色:实现了AbstractProduct接口的具体产品,也是一个将被相应的具体工厂创建的产品对象,与业务相关。代码示例1:publicabstractclassAbstractProductA{2:}3:4:publicclassProductA1extendsAbstractProductA{5:publicStringtoString(){6:returnItisProductA1;7:}8:}9:10:publicclassProductA2extendsAbstractProductA{11:publicStringtoString(){12:returnItisProductA2;13:}14:}15:16:publicabstractclassAbstractProductB{17:}18:19:publicclassProductB1extendsAbstractProductB{20:publicStringtoString(){21:returnItisProductB1;22:}23:}24:25:publicclassProductB2extendsAbstractProductB{26:publicStringtoString(){27:returnItisProductB2;28:}29:}30:31:publicabstractclassAbstractFactory{32:publicabstractAbstractProductACreateProductA();33:publicabstractAbstractProductBcreateProductB();34:}35:36:publicclassConcreteFactory1extendsAbstractFactory{37:publicAbstractProductACreateProductA(){38:returnnewProductA1();39:}40:publicAbstractProductBcreateProductB(){41:returnnewProductB1();42:}43:}44:45:publicclassConcreteFactory2extendsAbstractFactory{46:publicAbstractProductACreateProductA(){47:returnnewProductA2();48:}49:publicAbstractProductBcreat