一、引言
在设计模式 - 抽象工厂模式:统一不同代码风格下的代码级别中,我们介绍了抽象工厂模式,并结合家具厂与 Spring BeanFactory 实例,说明了如何寻找正确抽象。今天,我们继续深入工厂系列,学习更简单、使用频率更高的工厂方法模式(Factory Method Pattern)。该模式专注于围绕单一接口的对象创建,封装实例化过程,为项目带来更灵活、更易扩展的创建方式。
二、模式原理分析
定义:定义一个用于创建对象的接口,让实现该接口的类决定具体实例化哪个类。
目的:封装对象创建,提升方法可复用性,将实例化延迟到子类。
UML 三大角色
- 抽象产品(Product):声明所需产品的接口;
- 核心工厂(Creator):定义创建产品的抽象方法或静态方法;
- 具体产品(ConcreteProduct)/具体工厂(ConcreteCreator):实现抽象产品接口,并在工厂中实例化。
IProduct ←─────────── ProductFactory Product_A_Impl
▲ │ getProduct(name) implements IProduct
│ └─── returns ConcreteProduct ─────────► use()
Product_B_Impl
implements IProduct
三、代码实现示例
// 抽象产品
public interface IProduct {
void apply();
}
// 核心工厂
public class ProductFactory {
public static IProduct getProduct(String name) {
if ("a".equals(name)) {
return new ProductA();
}
return new ProductB();
}
}
// 具体产品A
public class ProductA implements IProduct {
@Override
public void apply() {
System.out.println("使用 A 产品");
}
}
// 具体产品B
public class ProductB implements IProduct {
@Override
public void apply() {
System.out.println("使用 B 产品");
}
}
// 客户端调用
public static void main(String[] args) {
IProduct p1 = ProductFactory.getProduct("");
p1.apply(); // 使用 B 产品
IProduct p2 = ProductFactory.getProduct("a");
p2.apply(); // 使用 A 产品
}
- 通过
ProductFactory.getProduct()
封装创建逻辑 - 客户端只依赖
IProduct
接口,实现使用与创建分离
四、使用场景分析
工厂方法模式常见于:
- 大量同类对象重复创建,如 DAO、VO 对象;
- 创建依赖外部资源,如读取配置、获取授权;
- 统一管理生命周期,如会话、浏览轨迹;
- 池化对象,如连接池、线程池;
- 隐藏真实类型,屏蔽复杂构造参数。
案例:MyBatis 的 LogFactory
MyBatis 通过 LogFactory
封装日志实现切换:
public interface Log { /* 原子操作方法 */ }
public final class LogFactory {
private static Constructor<? extends Log> logConstructor;
static {
tryImplementation(LogFactory::useSlf4j);
… // 依次尝试不同日志实现
}
public static Log getLog(String name) {
return logConstructor.newInstance(name);
}
}
- 核心工厂:
LogFactory
- 抽象产品:
Log
接口 - 具体产品:
Slf4jImpl
、Log4jImpl
、Jdk14LoggingImpl
等 - 增加新的日志框架,只需新增实现类并在静态初始化中注册
五、为什么要用工厂方法模式?
- 分离创建与使用,降低耦合,便于重构;
- 减少重复代码,将创建逻辑集中管理;
- 统一管理多种实现,扩展或切换只需修改工厂。
六、优缺点
优点
- 根据需求定制化创建对象
- 隐藏具体实现,提高可替换性(符合 LSP)
- 满足开闭原则,易于扩展新的产品实现
缺点
- 接口新增方法时,所有具体工厂需跟进,增加维护成本
- 具体工厂实现可能各异,若缺乏统一规范,增加理解难度
七、总结与对比
- 工厂方法模式:聚焦于单一抽象产品的继承扩展,适合简单场景;
- 抽象工厂模式:侧重多种抽象产品的组合扩展,适合复杂系统。
两者都封装了对象创建,但分别关注继承与组合两个维度。