1. 为什么需要工厂

当业务代码直接使用 new 创建具体对象时,调用方会同时依赖对象的接口和实现。实现类型一多,创建参数、选择规则与调用逻辑就会混在一起。工厂模式把“创建哪个对象、怎样创建”集中到独立组件中,让调用方只面向稳定的抽象。

适合使用工厂的场景包括:

  • 需要根据配置、类型或运行环境创建不同实现;
  • 对象创建过程复杂,需要统一校验、组装依赖或复用实例;
  • 希望新增实现时尽量减少对调用方的修改。

如果系统始终只有一个简单实现,直接构造通常更清晰,不必为了模式而增加间接层。

2. 简单工厂

下面以消息通知为例。调用方只依赖 Notifier,由工厂根据类型选择实现。

public interface Notifier {
void send(String message);
}
public final class EmailNotifier implements Notifier {
@Override
public void send(String message) {
System.out.println("Email: " + message);
}
}
public final class SmsNotifier implements Notifier {
@Override
public void send(String message) {
System.out.println("SMS: " + message);
}
}
public final class NotifierFactory {
private NotifierFactory() {}
public static Notifier create(String type) {
return switch (type.toLowerCase()) {
case "email" -> new EmailNotifier();
case "sms" -> new SmsNotifier();
default -> throw new IllegalArgumentException("Unsupported notifier: " + type);
};
}
}
Notifier notifier = NotifierFactory.create("email");
notifier.send("构建完成");

简单工厂容易理解,也便于集中管理创建规则;它的代价是每增加一种类型通常都要修改工厂中的分支。

3. 工厂方法

当不同产品的创建过程需要独立扩展时,可以把创建动作下放给各自的工厂实现。

public interface NotifierFactory {
Notifier create();
}
public final class EmailNotifierFactory implements NotifierFactory {
@Override
public Notifier create() {
return new EmailNotifier();
}
}
public final class SmsNotifierFactory implements NotifierFactory {
@Override
public Notifier create() {
return new SmsNotifier();
}
}

调用方可以通过构造参数接收工厂,从而不关心具体产品:

public final class AlertService {
private final NotifierFactory factory;
public AlertService(NotifierFactory factory) {
this.factory = factory;
}
public void alert(String message) {
factory.create().send(message);
}
}

4. 如何选择

方案适用情况主要代价
直接构造单一、稳定且创建简单调用方依赖具体实现
简单工厂类型有限,选择规则集中新增类型需要修改分支
工厂方法产品族持续扩展,创建逻辑各不相同类与接口数量增加

核心判断不是“能否使用工厂”,而是对象创建是否已经成为独立的变化点。只有变化值得隔离时,工厂带来的扩展性才大于它增加的复杂度。