参考:1.《图解设计模式》 https://www.cnblogs.com/Bobby0322/p/4179921.html https://blog.csdn.net/qqqqq1993qqqqq/article/details/77332087 https://blog.csdn.net/w372426096/article/details/78009310 http://coderzcr.top/index.php/archives/14/#directory093554344830054631
模式定义
- 工厂方法模式又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂模式(Polymorphic Factory) ;
父类负责定义创建对象的公共接口,而子类则负责生成具体的对象,这样做的目的是将类的实例化操作延迟到子类中完成,即由子类来决定究竟应该实例化(创建)哪一个类。
解决何种问题
在简单工厂模式中,将实例化对象的工作推迟到了专门负责创建对象的工厂类中,这样,在我们事先预知的情况下,可以根据我们的需要动态创建产品类。;
- 但是,我们的预知是有限的,客户的变化可能是无限的。所以,就出现了问题,一旦客户的变化超越了我们的预知,我们就必须修改我们的源代码了。这是设计模式所不允许的 ;
- 问题:具体工厂类的创建工作不能满足我们的要求了,创建的工作变化了;
- 解决思路:哪里变化,封装哪里。把具体工厂封装起来。
模式适合场景
- 创建对象需要大量重复的代码;
- 创建对象需要访问某些信息,而这些信息不应该包含在复合类中;
- 创建对象的生命周期必须集中管理,以保证在整个程序中具有一致的行为。
代码示例
下面以日产汽车工厂为例
UML类图如下:

/*** 日产车*/abstract class NissanCar {String name;void printCar(){System.out.println(name+"汽车已制造完成");}}
日产各类车型
/*** 车型:逍客*/class Xtrail extends NissanCar {Xtrail(){this.name = "逍客";}}/*** 车型:轩逸*/class Sylphy extends NissanCar {Sylphy(){this.name = "轩逸";}}/*** 车型:天籁*/class Altima extends NissanCar {Altima(){this.name="天籁";}}
/*** 日产车工厂*/public abstract class NissanCarFactory {/*** 生产汽车*/abstract NissanCar createCar() ;}
各车型工厂
/*** 天籁工厂*/public class AltimaFactory extends NissanCarFactory {//不能为public,强迫通过工厂生成实例对象@OverrideNissanCar createCar() {return new Altima();}}/*** 逍客工厂*/public class XtrailFactory extends NissanCarFactory {//不能为public,强迫通过工厂生成实例对象@OverrideNissanCar createCar() {return new Xtrail();}}/*** 轩逸工厂*/public class SylphyFactory extends NissanCarFactory {//不能为public,强迫通过工厂生成实例对象@OverrideNissanCar createCar() {return new Sylphy();}}
工厂方法模式结构如下:

JDK里的Factory Method模式
- Collection中的Iterator方法 : 对于
iterator()方法来说Collection就是一个根抽象工厂,下面还有List等接口作为抽象工厂,再往下有ArrayList等具体工厂 - JDBC: 在使用
JDBC进行数据库开发时,如果数据库由MySQL改为Oracle或其他,则只需要改一下数据库驱动名称就可以,其他都不用修改(前提是使用的都是标准SQL语句); - 如果需要设计一个连接邮件服务器的框架,那么就要考虑到连接邮件服务器有几种方式:
POP3、SMTP、HTTP。就可以定义一个连接邮件服务器接口,在此接口中定义一些对邮件操作的接口方法,把这三种连接方式封装成产品类,实现接口中定义的抽象方法。再定义抽象工厂和具体工厂,当选择不同的工厂时,对应到产生相应的连接邮件产品对象。采用这种工厂方法模式的设计,就可以做到良好的扩展性。比如某些邮件服务器提供了WebService接口,只需要增加一个产品类和工厂类就可以了,而不需要修改原来代码; - Spring框架中的Bean工厂,这是一个复杂对象,所以适合用工厂模式 。
