参考: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类图如下:

工厂方法模式 - 图1

  1. /**
  2. * 日产车
  3. */
  4. abstract class NissanCar {
  5. String name;
  6. void printCar(){
  7. System.out.println(name+"汽车已制造完成");
  8. }
  9. }

日产各类车型

  1. /**
  2. * 车型:逍客
  3. */
  4. class Xtrail extends NissanCar {
  5. Xtrail(){
  6. this.name = "逍客";
  7. }
  8. }
  9. /**
  10. * 车型:轩逸
  11. */
  12. class Sylphy extends NissanCar {
  13. Sylphy(){
  14. this.name = "轩逸";
  15. }
  16. }
  17. /**
  18. * 车型:天籁
  19. */
  20. class Altima extends NissanCar {
  21. Altima(){
  22. this.name="天籁";
  23. }
  24. }
  1. /**
  2. * 日产车工厂
  3. */
  4. public abstract class NissanCarFactory {
  5. /**
  6. * 生产汽车
  7. */
  8. abstract NissanCar createCar() ;
  9. }

各车型工厂

  1. /**
  2. * 天籁工厂
  3. */
  4. public class AltimaFactory extends NissanCarFactory {
  5. //不能为public,强迫通过工厂生成实例对象
  6. @Override
  7. NissanCar createCar() {
  8. return new Altima();
  9. }
  10. }
  11. /**
  12. * 逍客工厂
  13. */
  14. public class XtrailFactory extends NissanCarFactory {
  15. //不能为public,强迫通过工厂生成实例对象
  16. @Override
  17. NissanCar createCar() {
  18. return new Xtrail();
  19. }
  20. }
  21. /**
  22. * 轩逸工厂
  23. */
  24. public class SylphyFactory extends NissanCarFactory {
  25. //不能为public,强迫通过工厂生成实例对象
  26. @Override
  27. NissanCar createCar() {
  28. return new Sylphy();
  29. }
  30. }

工厂方法模式结构如下:

工厂方法模式 - 图2

JDK里的Factory Method模式

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

总结

优点

  • 工厂方法模式的优点包括简单工厂方法模式的优点:用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
  • 而且解决了简单工厂存在的不符合开闭原则问题,
    在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

    缺点

  • 只能创建一类对象,这在后面的抽象工厂模式中解决