工厂模式学习笔记

核心思想与引入动机

工厂模式的精髓在于:将对象的创建控制权交给一个专门负责创建对象的工厂类,而不是在客户端中直接通过 new 来实例化对象

那么,为什么要这么做?

在实际开发中,如果某一类对象存在大量实现类,按照最直接的方式,客户端就需要频繁地使用 new 来创建不同的实现对象。这种做法会带来多个明显的问题。


直接 new 对象带来的问题

1. 强耦合问题

当客户端直接 new 某个具体实现类时,就意味着客户端与该实现类之间形成了强依赖关系
一旦需要将同一抽象下的实现类替换为另一个实现,就必须修改客户端源码。这显然违背了开闭原则(对扩展开放,对修改关闭)

2. 不利于测试与扩展

由于对象是在客户端内部通过 new 创建的,测试时无法将模拟对象(Mock)或测试实现注入进来。
这会导致单元测试困难、模块隔离性差,也不利于后期的功能扩展和维护。

总结:对象创建逻辑与业务逻辑耦合在一起,是问题的根源。


工厂模式的基本解决思路

为了解决上述问题,引入了工厂模式。

工厂模式的核心做法是:
将“创建对象”这件事统一交给工厂类完成,客户端只负责“使用对象”

客户端不再直接依赖具体实现类,而是:

  1. 依赖一个工厂类
  2. 将必要的参数传递给工厂
  3. 工厂根据参数返回对应对象

这样,客户端就不再直接依赖实现类,而是依赖工厂,解耦得到了明显改善。


开闭原则下的工厂设计优化

如果工厂只是一个类,内部包含所有对象的创建逻辑,那么新增对象时依旧需要修改工厂类,仍然不符合开闭原则。

优化方法

  1. 将工厂设计为抽象接口
  2. 每种产品的具体工厂实现该接口
  3. 新增产品时,只需新增对应工厂实现类,无需修改原有工厂

客户端只依赖抽象工厂接口,根据需求创建对应具体工厂,再通过工厂生成产品对象。
这样就实现了开闭原则:对扩展开放,对修改关闭。


产品过多时的进一步优化 —— 抽象工厂模式

如果产品数量过多,每个产品都需要单独的工厂类,会导致工厂类数量激增。
此时可以采用抽象工厂模式

  1. 将相关产品(产品族)组合在一起,例如“手机 + 口罩”
  2. 创建一个能够生产产品族的工厂接口
  3. 不同具体工厂(如华为、小米)实现该接口
  4. 客户端只需指定所需工厂类型,工厂内部负责生产对应产品族

总结
抽象工厂模式实际上是“创建工厂的工厂”,客户端通过工厂接口调用,不再直接关心具体产品的创建细节,解耦更彻底,也便于扩展。