工厂模式:用简单工厂/工厂方法封装不同后端的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),且不会频繁新增 | 后端类型多,或未来可能扩展 |
下面这张图能帮你直观感受两种模式在结构上的差异:
5. 在实际项目中怎么选?
我个人有个简单的判断标准:
- 后端类型 ≤ 3 个,且基本不会加——用简单工厂。代码少,够用就行。
- 后端类型 ≥ 4 个,或者明确知道未来要加——用工厂方法。虽然多写几个类,但后面扩展起来非常舒服。
- 同一套代码要给多个客户部署,每个客户用不同后端——工厂方法更是首选。配合配置文件或SPI机制,连编译都不用动。
enum 而不是字符串做参数。
ApplicationContext.getBean() 拿到对应工厂,连 new 都不用写。代码会变得非常干净。
6. 说到底
工厂模式不是什么高深的东西。它就是帮我们把"创建SDK"这件破事集中管理起来。你想想看,以后要加一个新的后端支持,是满世界找 new XxxClient() 舒服,还是新增一个工厂类舒服?
我在项目里封装过多套SDK适配层,工厂模式每次都是核心。不管是简单工厂还是工厂方法,选一个适合你的场景,先把实例化逻辑收住,后面你会感谢自己的。