02-曹操献刀:工厂方法模式
2.1、模式背景故事
曹操从王允处借七星宝刀刺杀董卓
2.2、模式定义
所谓工厂方法模式(Factory Method Pattern),就是定义一个创建产品对象的工厂接口,让子类决定实例化哪一种实例对象,也就是将实际创建实例对象的工作推迟到子类当中,核心工厂类不再负责具体产品的创建。
工厂方法模式是对简单工厂模式进行了抽象。如此一来核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。工厂方法模式完全实现“开-闭”原则,对扩展开放,对修改关闭。在不影响现有软件结构的基础上实现了扩展,可应用于更复杂的层次结构和产品结果复杂的场合。
2.3、工厂方法模式的静态建模
大司徒王允---抽象工厂
各类宝刀---抽象产品
校尉曹操---具体工厂
七星宝刀---具体产品
图中所描述的内容是:抽象工厂ISwordFactory生产抽象产品AbstractSword,具体工厂Caocao生产具体产品QixingSword;具体工厂Caocao实现抽象工厂ISwordFactory接口,具体产品QixingSword是抽象产品的一个子类。这也就是我们故事中蕴含的工厂方法设计模式!
2.4、故事的工厂方法模式实现
2.4.1)建立产品
1)抽象宝刀---AbstractSword
package com.demo.factory.model; /** * Created by lsq on 2018/3/12. * 定义抽象宝刀 */ public abstract class AbstractSword { //宝刀的名称 private String name; //抽象父类的构造方法 public AbstractSword(){ } //获得宝刀名称 public String getName(){ return name; } //设置宝刀名称 public void setName(String name){ this.name = name; } }
2)具体宝刀---QixingSword七星宝刀
package com.demo.factory.model.object; import com.demo.factory.model.AbstractSword; /** * Created by lsq on 2018/3/12. * 七星宝刀 */ public class QixingSword extends AbstractSword { /** * 构造方法设置宝刀的名称 */ public QixingSword(){ this.setName("七星宝刀"); } }
2.4.2)建立工厂
1)抽象宝刀工厂---ISwordFactory生产抽象宝刀
package com.demo.factory.itf; import com.demo.factory.model.AbstractSword; /** * Created by lsq on 2018/3/12. * 宝刀工厂 */ public interface ISwordFactory { /** * 生产各类宝刀(返回值是抽象宝刀类型) * @return */ public AbstractSword createSword(); }
2)具体宝刀工厂---Caocao生产七星宝刀
package com.demo.factory; import com.demo.factory.itf.ISwordFactory; import com.demo.factory.model.AbstractSword; import com.demo.factory.model.object.QixingSword; /** * Created by lsq on 2018/3/12. * 曹操具体工厂 */ public class Caocao implements ISwordFactory{ /** * 实现ISwordFactory接口的createSword方法,生产七星宝刀 * @return */ public AbstractSword createSword() { return new QixingSword(); } }
2.4.3)测试
1)运行
import com.demo.factory.Caocao; import com.demo.factory.itf.ISwordFactory; import com.demo.factory.model.AbstractSword; /** * Created by lsq on 2018/3/12. * */ public class MainApp { public static void main(String[] args) { //创建曹操实例对象(返回使用接口类型ISwordFactory) ISwordFactory swordFactory = new Caocao(); //获得宝刀实例-七星宝刀 AbstractSword sword = swordFactory.createSword(); //刺杀董卓 System.out.println("曹操使用"+sword.getName()+"刺杀董卓!"); } }
运行结果:
2)使用八星宝刀来考验模式
1)创建八星宝刀---BaxingSword
package com.demo.factory.model.object; import com.demo.factory.model.AbstractSword; /** * Created by lsq on 2018/3/12. * 八星宝刀 */ public class BaxingSwrod extends AbstractSword{ /** * 构造方法设置宝刀的名称 */ public BaxingSwrod(){ this.setName("八星宝刀"); } }
2)创建八星宝刀工厂---Caocao2生产八星宝刀
package com.demo.factory; import com.demo.factory.itf.ISwordFactory; import com.demo.factory.model.AbstractSword; import com.demo.factory.model.object.BaxingSwrod; /** * Created by lsq on 2018/3/12. * 曹操具体工厂 */ public class Caocao2 implements ISwordFactory{ /** * 实现ISwordFactory接口的createSword方法,生产八星宝刀 * @return */ public AbstractSword createSword() { return new BaxingSwrod(); } }
3)测试结果
在这一系列的变化过程中,应用的是程序设计语言中的多态方式,使用接口调用对象实例的具体方法,获得不同对象内容,而对外部是表现一致的(相同的方法),这也是面向接口编程的优点。
像这种不在工厂中产生具体的对象实例,而是将实例化的工作推迟到工厂子类中,这种模式被称做工厂方法模式。
我们可以这样理解工厂方法设计模式:
1)抽象工厂生产抽象产品(ISwordFactory生产AbstractSword),具体工厂生产具体产品(Caocao类生产QixingSword);
2)抽象对具体(具体类实现抽象类,如Caocao类实现ISwordFactory;QixingSword继承AbstractSword)。
2.6使用场合
(1)当子类型可能会很多,以后需要不断增添不同的子类实现时;
(2)当一个系统尚在框架设计阶段,还不知道将来需要实例化哪些具体类时;
(3)系统设计之初不需要具体对象的概念(或者说没有具体对象的概念)。
以上几种情况比较适合工厂方法设计模式。通过子类来创造对象,工厂方法模式在此过程中负责将客户端从具体类型中解耦,客户端只需要知道他们使用对象的抽象类型就可以了,而不必关心具体的对象类型,具体的对象类型由工厂子类负责创建。