Skip to content

工厂方法模式 (Factory Method Pattern) ​

模式定义 ​

工厂方法模式是一种创建型设计模式,它定义了一个创建对象的接口,但让子类决定要实例化哪个类。工厂方法将对象的创建延迟到子类。

简单工厂 vs 工厂方法 vs 抽象工厂 ​

特性简单工厂工厂方法抽象工厂
创建方式一个工厂类每个产品一个工厂一个工厂创建产品族
扩展性差(需修改工厂)好(新增工厂即可)好
符合原则违反开闭原则符合开闭原则符合开闭原则
适用场景产品种类少产品种类多产品族

实现示例:通知系统 ​

产品接口 ​

java
// 通知产品接口
public interface Notification {
    void send(String title, String message);
}

// 邮件通知
public class EmailNotification implements Notification {
    @Override
    public void send(String title, String message) {
        System.out.println("发送邮件通知 - 标题: " + title + ", 内容: " + message);
    }
}

// 短信通知
public class SmsNotification implements Notification {
    @Override
    public void send(String title, String message) {
        System.out.println("发送短信通知 - 标题: " + title + ", 内容: " + message);
    }
}

// 推送通知
public class PushNotification implements Notification {
    @Override
    public void send(String title, String message) {
        System.out.println("发送推送通知 - 标题: " + title + ", 内容: " + message);
    }
}

方式一:简单工厂 ​

java
public class NotificationFactory {
    public static Notification createNotification(String type) {
        if (type == null || type.isEmpty()) {
            throw new IllegalArgumentException("通知类型不能为空");
        }
        switch (type.toLowerCase()) {
            case "email":
                return new EmailNotification();
            case "sms":
                return new SmsNotification();
            case "push":
                return new PushNotification();
            default:
                throw new IllegalArgumentException("未知的通知类型: " + type);
        }
    }
}

// 使用
// Notification notification = NotificationFactory.createNotification("email");
// notification.send("标题", "内容");

缺点: 每次新增通知类型都需要修改工厂类,违反开闭原则。

方式二:工厂方法模式 ​

java
// 工厂接口
public interface NotificationFactory {
    Notification createNotification();
}

// 邮件工厂
public class EmailNotificationFactory implements NotificationFactory {
    @Override
    public Notification createNotification() {
        return new EmailNotification();
    }
}

// 短信工厂
public class SmsNotificationFactory implements NotificationFactory {
    @Override
    public Notification createNotification() {
        return new SmsNotification();
    }
}

// 推送工厂
public class PushNotificationFactory implements NotificationFactory {
    @Override
    public Notification createNotification() {
        return new PushNotification();
    }
}

使用示例 ​

java
public class NotificationService {
    private final NotificationFactory factory;

    public NotificationService(NotificationFactory factory) {
        this.factory = factory;
    }

    public void sendNotification(String title, String message) {
        Notification notification = factory.createNotification();
        notification.send(title, message);
    }
}

// 测试代码
public class FactoryMethodDemo {
    public static void main(String[] args) {
        // 使用邮件通知
        NotificationService emailService = new NotificationService(new EmailNotificationFactory());
        emailService.sendNotification("会议通知", "明天下午3点开会");

        // 使用短信通知
        NotificationService smsService = new NotificationService(new SmsNotificationFactory());
        smsService.sendNotification("验证码", "您的验证码是 123456");

        // 使用推送通知
        NotificationService pushService = new NotificationService(new PushNotificationFactory());
        pushService.sendNotification("新消息", "您有一条新的消息");
    }
}

方式三:泛型工厂方法 ​

使用泛型简化工厂方法的实现。

java
// 泛型工厂接口
public interface GenericFactory<T> {
    T create();
}

// 邮件工厂(泛型版本)
public class EmailFactory implements GenericFactory<EmailNotification> {
    @Override
    public EmailNotification create() {
        return new EmailNotification();
    }
}

// 短信工厂(泛型版本)
public class SmsFactory implements GenericFactory<SmsNotification> {
    @Override
    public SmsNotification create() {
        return new SmsNotification();
    }
}

JDK 中的工厂方法 ​

1. Calendar 类 ​

java
// Calendar.getInstance() 就是工厂方法
Calendar calendar = Calendar.getInstance(); // 根据时区返回不同实现

2. NumberFormat 类 ​

java
NumberFormat currencyFormat = NumberFormat.getCurrencyInstance();
NumberFormat percentFormat = NumberFormat.getPercentInstance();

3. Collection.iterator() ​

java
List<String> list = new ArrayList<>();
Iterator<String> iterator = list.iterator(); // 每个集合类有自己的迭代器实现

实际应用 ​

  • Spring BeanFactory: 通过 getBean() 方法创建对象
  • SLF4J LoggerFactory: 根据配置返回不同的 Logger 实现
  • JDBC DriverManager: 根据 URL 创建不同的数据库连接
  • 日志框架: Log4j、Logback 等通过工厂方法创建 Logger

优缺点 ​

优点:

  • 符合开闭原则,新增产品只需新增工厂
  • 每个工厂只负责创建一种产品,职责清晰
  • 引入抽象层,提高系统灵活性

缺点:

  • 类数量成倍增加,增加系统复杂度
  • 增加了系统的抽象性和理解难度