工厂模式:用简单工厂/工厂方法封装不同后端的SDK实例化

你有没有遇到过这种情况?项目里对接多个云存储,今天用阿里云OSS,明天客户要求换AWS S3,后天又来一个私有化部署要用MinIO。每次切换,代码里到处都是 new XxxClient(),改起来想死的心都有。

说白了,直接实例化SDK就是把命运交给了具体实现。耦合度高,切换成本大。我之前有个项目,SDK实例化代码散落在各个业务类里,换后端时改了四十多个文件……嗯,从那以后,我下定决心用工厂模式来管这事。

1. 为什么非要用工厂?

直接 new SDK 客户端,至少有三个问题:

  • 硬编码依赖——业务代码里到处是具体后端类型,换一家就得改源码
  • 重复配置——每次实例化都要传一遍AK、SK、Endpoint,写多了容易漏
  • 不易扩展——新增后端支持,得在所有调用处加if-else,想想就头疼

工厂模式正好来解这个局。它把"怎么创建SDK"和"怎么用SDK"拆开。业务方只管调用接口,不用关心背后new的是哪个后端。我个人习惯,只要SDK实例化逻辑可能变化,第一反应就是上工厂。

2. 简单工厂:最快入手

简单工厂的思路很直接——搞一个专门的类,根据参数返回对应的SDK实例。咱们先看代码:

public class SDKFactory {
    public static SDK createSDK(String type) {
        if ("ALIYUN".equals(type)) {
            return new AliyunOSSClient();
        } else if ("AWS".equals(type)) {
            return new AWSS3Client();
        } else if ("MINIO".equals(type)) {
            return new MinIOClient();
        }
        throw new IllegalArgumentException("未知后端类型: " + type);
    }
}

客户端调用变成这样:

SDK sdk = SDKFactory.createSDK("ALIYUN");
sdk.uploadFile("bucket", "key", data);

是不是清爽多了?所有创建逻辑收拢到一个地方,业务代码里再也看不到具体类名。

优点很明显:结构简单,代码量少,适合后端类型少且稳定的场景。

缺点也有:每次新增后端都要改工厂类的if-else,违背了"开闭原则"。我之前有次就是这样,加了第四个后端后,工厂类变得臃肿不说,测试时还得考虑所有分支……嗯,从那以后,我开始关注工厂方法。

3. 工厂方法:更优雅的扩展

工厂方法把"创建"这件事抽象成接口,每个具体后端对应一个子工厂。来看代码:

// 抽象工厂接口
public interface SDKFactory {
    SDK createSDK();
}

// 具体工厂
public class AliyunOSSFactory implements SDKFactory {
    public SDK createSDK() {
        return new AliyunOSSClient();
    }
}

public class AWSS3Factory implements SDKFactory {
    public SDK createSDK() {
        return new AWSS3Client();
    }
}

public class MinIOFactory implements SDKFactory {
    public SDK createSDK() {
        return new MinIOClient();
    }
}

客户端使用:

SDKFactory factory = new AliyunOSSFactory();
SDK sdk = factory.createSDK();

你想想看,现在要加一个华为云OBS,我只要新增一个 OBSFactory 实现 SDKFactory 接口,现有的工厂类一个都不用改。这就是开闭原则的魅力。

当然,代价是多了一些类。后端种类越多,这种投入越值。

4. 两种模式,一张表说清

维度 简单工厂 工厂方法
核心思路 一个类集中创建 抽象接口 + 子类实现
扩展方式 修改工厂类 新增具体工厂类
是否符合开闭原则 否 是
代码复杂度 低 中等
类数量 1个工厂 + N个SDK 1个接口 + N个工厂 + N个SDK
适合场景 后端类型少(≤3),且不会频繁新增 后端类型多,或未来可能扩展

下面这张图能帮你直观感受两种模式在结构上的差异:

多后端SDK实例化 —— 工厂模式对比 简单工厂模式 客户端(Client) SDKFactory createSDK() OSS SDK S3 SDK MinIO SDK 工厂方法模式 客户端(Client) SDKFactory(接口) AliyunFactory AWSFactory MinIOFactory OSS SDK S3 SDK MinIO SDK 简单工厂特点 一个工厂类通过参数判断创建不同SDK 新增后端需修改工厂类(违反开闭原则) 工厂方法特点 每个后端对应一个具体工厂子类 新增后端只需新增子类(符合开闭原则)

5. 在实际项目中怎么选?

我个人有个简单的判断标准:

  • 后端类型 ≤ 3 个,且基本不会加——用简单工厂。代码少,够用就行。
  • 后端类型 ≥ 4 个,或者明确知道未来要加——用工厂方法。虽然多写几个类,但后面扩展起来非常舒服。
  • 同一套代码要给多个客户部署,每个客户用不同后端——工厂方法更是首选。配合配置文件或SPI机制,连编译都不用动。
我曾经踩过一个坑: 简单工厂里用字符串做类型判断,结果有个地方传参传错了,运行时才发现。后来我改成用枚举,编译期就能检查出来。如果你用简单工厂,建议用 enum 而不是字符串做参数。
一个小技巧: 工厂方法配合 Spring 的依赖注入,可以把具体工厂注册成 Bean。客户端通过 ApplicationContext.getBean() 拿到对应工厂,连 new 都不用写。代码会变得非常干净。

6. 说到底

工厂模式不是什么高深的东西。它就是帮我们把"创建SDK"这件破事集中管理起来。你想想看,以后要加一个新的后端支持,是满世界找 new XxxClient() 舒服,还是新增一个工厂类舒服?

我在项目里封装过多套SDK适配层,工厂模式每次都是核心。不管是简单工厂还是工厂方法,选一个适合你的场景,先把实例化逻辑收住,后面你会感谢自己的。