Skip to content
Method约 1 分钟0 个小节更新于 2026/06/19在线编辑

工厂模式

工厂模式用于封装对象创建逻辑,让客户端不直接依赖具体类。

当创建对象的逻辑开始变复杂,或者对象类型会随着业务变化不断增加时,就可以考虑工厂模式。

解决什么问题

直接在业务代码里到处 new 会带来几个问题:

  • 客户端知道太多具体类。
  • 创建逻辑散落在各个地方。
  • 新增类型时要修改很多业务代码。
  • 构造参数复杂时,调用方很容易写错。

工厂模式把“创建哪个对象、怎么创建”集中到专门的工厂中。

简单工厂

简单工厂不是 GoF 经典 23 种之一,但实际开发中非常常见。

场景

订单系统支持多种支付方式:微信、支付宝、银行卡。

java
interface PayClient {
    void pay(long orderId, int amount);
}

class WechatPayClient implements PayClient {
    public void pay(long orderId, int amount) {
        System.out.println("wechat pay");
    }
}

class AlipayClient implements PayClient {
    public void pay(long orderId, int amount) {
        System.out.println("alipay pay");
    }
}

工厂负责创建:

java
class PayClientFactory {
    public static PayClient create(String type) {
        if ("wechat".equals(type)) {
            return new WechatPayClient();
        }
        if ("alipay".equals(type)) {
            return new AlipayClient();
        }
        throw new IllegalArgumentException("unsupported pay type: " + type);
    }
}

使用:

java
PayClient client = PayClientFactory.create("wechat");
client.pay(1001L, 5000);

特点

简单工厂能把对象创建集中起来,但新增类型时仍然要修改工厂类,所以不完全符合开闭原则。

适合类型较少、变化不频繁的场景。

工厂方法

工厂方法把创建逻辑延迟到子类,每个具体工厂负责创建一种产品。

java
interface PayClientFactory {
    PayClient create();
}

class WechatPayClientFactory implements PayClientFactory {
    public PayClient create() {
        return new WechatPayClient();
    }
}

class AlipayClientFactory implements PayClientFactory {
    public PayClient create() {
        return new AlipayClient();
    }
}

使用:

java
PayClientFactory factory = new WechatPayClientFactory();
PayClient client = factory.create();

工厂方法更符合开闭原则。新增支付方式时,新建一个产品类和一个工厂类即可,不需要修改原来的工厂。

缺点是类数量会增加。

抽象工厂

抽象工厂用于创建一组相关对象,也叫“产品族”。

场景

不同云厂商都提供短信和对象存储能力:

text
腾讯云产品族:TencentSmsClient + TencentOssClient
阿里云产品族:AliyunSmsClient + AliyunOssClient

抽象产品:

java
interface SmsClient {
    void send(String phone, String message);
}

interface OssClient {
    void upload(String fileName);
}

抽象工厂:

java
interface CloudFactory {
    SmsClient createSmsClient();

    OssClient createOssClient();
}

具体工厂:

java
class TencentCloudFactory implements CloudFactory {
    public SmsClient createSmsClient() {
        return new TencentSmsClient();
    }

    public OssClient createOssClient() {
        return new TencentOssClient();
    }
}

class AliyunCloudFactory implements CloudFactory {
    public SmsClient createSmsClient() {
        return new AliyunSmsClient();
    }

    public OssClient createOssClient() {
        return new AliyunOssClient();
    }
}

当系统需要整体切换云厂商时,只要切换工厂即可。

三者区别

类型关注点适合场景主要问题
简单工厂一个工厂创建多种产品类型少,变化少新增产品要改工厂
工厂方法一个工厂创建一种产品产品经常扩展类数量增加
抽象工厂创建一组相关产品产品族整体切换新增产品等级困难

使用场景

  • 根据配置创建不同实现。
  • 第三方渠道接入,例如支付、短信、存储、物流。
  • 对象创建过程复杂,不希望业务代码关心细节。
  • 框架需要根据类型创建处理器。

实战注意

  • 类型少时,简单工厂就够了。
  • 产品不断增加时,再考虑工厂方法。
  • 需要成套切换一组实现时,再考虑抽象工厂。
  • 在 Spring 中,经常可以用 Map<String, Interface> 替代大量手写工厂。

以工程实践沉淀知识,以文档复盘成长。