设计模式 - 工厂方法模式(设计模式介绍系列)(二)

393 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第25天,点击查看活动详情

上一篇文章我们讲了工厂模式的基本用法,其实上一篇文章也可以被当做一个工厂模式思想的入门。这篇文章我们将对工厂模式相关的内容做具体的介绍。

工厂模式的分类

在很多资料中,会把工厂模式相关的设计模式分为三种:

  • 简单/静态工厂模式
  • 工厂方法模式
  • 抽象工厂模式

我们可以认为,简单工厂模式工厂方法模式的简版,而抽象工厂模式工厂方法模式的加强版。

使用工厂模式的好处

使用工厂模式的好处就是,使用方完全不用感知对象是怎么创建出来的,只需要知道工厂的提供的接口就可以了。这样就可以做到使用者和被使用的类的“解耦”。

如果不使用工厂模式,比如说要创建一个类A 的对象,我们需要在使用者的代码块中使用new A() 来创建一个新的对象。这样类A 就和使用者“耦合”了。

如果类A 内部需要改动什么东西,使用了工厂模式,就完全不需要使用者关心这个改动了;如果没有使用工厂模式,使用者就有可能会改动很多。

举例来说我们对于文件IO 的操作

Reader reader = new BufferedReader(new FileReader(new File("copy.txt")));

如果使用者有很多使用上述代码的情况,这个时候我们要将BufferedReader 换成其他类型的Reader 实现,那么就需要改动很多位置。但是如果使用了工厂模式,上述逻辑都在我们对应的Factory 内部实现,我们只需要变更对应的Factory 内部逻辑就好。


简单工厂方法模式我们可以参考上一篇文章,上一篇文章就是一个典型的简单工厂模式的实现。

这里我们给出“简单工厂模式”的类图,供读者参考:

Screen Shot 2022-04-25 at 2.24.58 PM.png

而这篇文章,我们重点介绍工厂方法模式。


工厂方法模式

工厂模式组织形式还是那句话:定义一个用于创建对象的接口,让子类决定去实例化哪一个类。工厂方法使一个类的实例化延迟到子类。

我们首先给出工厂方法模式的UML 类图,参照类图和后续给出的代码来学习“工厂方法模式”。

Screen Shot 2022-04-25 at 2.25.03 PM.png

步骤一

首先我们明确我们要创建的产品是什么,抽象出产品类型:

public interface Vehicle {

  void seats();
}

步骤二

针对具体产品,有具体的产品实体类:

// 小汽车类
public class Car implements Vehicle{
  @Override
  public void seats() {
    System.out.println("五座小汽车");
  }
}
// 卡车类
public class Truck implements Vehicle{
  @Override
  public void seats() {
    System.out.println("两座小卡车");
  }
}

步骤三

有了这些目标产品之后,我们就需要一个“汽车工厂”。这个汽车工厂可以创建任何类型的汽车。定义如下:

public interface VehicleFactory {
  Vehicle createVehicle();
}

步骤四

对于具体类型的产品,有不同的工厂来生产它们:

// 小汽车工厂
public class CarFactory implements VehicleFactory{
  @Override
  public Vehicle createVehicle() {
    return new Car();
  }
}
// 卡车工厂
public class TruckFactory implements VehicleFactory{
  @Override
  public Vehicle createVehicle() {
    return new Truck();
  }
}

上述声明完成之后,可以按照如下方法使用:

public static void main(String[] args) {
  // 如果想要一辆小汽车
  VehicleFactory carFactory = new CarFactory();
  carFactory.createVehicle().seats();
  // 如果想要一辆卡车
  VehicleFactory truckFactory = new TruckFactory();
  truckFactory.createVehicle().seats();
}

显示结果如下:

五座小汽车
两座小卡车

以上就是“工厂方法模式”的创建及使用流程。

总结

针对工厂方法模式的流程,通过对比类图和代码,结构也是比较清晰的。

从中我们也可以明显看出,客户端(使用者)不需要关心对象的创建,每个类有自己的明确职责。如果有新的对象(或者说对象类型)需要增加,我们只需要新增新的类和对应的工厂即可。对已有的结构不会产生任何影响。

但是比较明显的缺点就是如果使用场景不恰当,会新增很多额外的代码却没有什么其他收益。

所以不同的设计模式有其对应的应用场景,我们应该结果具体的场景具体分析,不要为了追求“设计模式”而生搬硬套。

这篇文章介绍的是“工厂方法模式”。在接下来的文章中我们会介绍工厂模式的另一个实现:抽象工厂模式。