网站首页 > 文章精选 正文
一、为什么需要工厂模式+ 策略模式?
单独使用策略模式时,客户端需要直接实例化具体策略类(如 new AiAuditStrategy()),这会导致两个问题:
- 客户端与具体策略强耦合:客户端必须知道所有策略类的细节(如类名、构造参数),违反 “迪米特法则”。
- 策略创建逻辑重复:若策略的创建需要复杂逻辑(如参数校验、依赖注入、配置读取),这些代码会在客户端重复出现,违背 “单一职责原则”。
而工厂模式的核心是封装对象创建逻辑,通过工厂类统一管理策略的实例化过程。两者结合后,客户端只需通过工厂获取策略实例(如
AiAuditStrategyFactory.getMediaType(1)),无需关心具体策略如何创建或切换,同时保持策略的动态替换能力。
二、工厂模式 + 策略模式解决的核心问题
1. 解耦客户端与具体策略
客户端只需通过工厂获取策略接口,无需知道具体策略类的细节(如类名、构造参数),符合 “依赖倒置原则”。
2. 封装复杂的创建逻辑
策略的创建可能涉及参数校验、资源初始化(如数据库连接)、配置读取等逻辑,这些代码被集中封装在工厂中,避免重复。
3. 支持动态切换策略
通过工厂的 “类型参数” 或 “配置”,可以在运行时动态选择策略(如根据用户选择切换支付方式),无需修改客户端代码。
4. 符合开闭原则
新增策略时,只需添加新的策略类和工厂的创建逻辑(如在工厂中注册新策略类型),无需修改现有客户端代码,扩展性强。
三、工厂模式 + 策略模式实战
3.1 需求
有个后台管理系统,可以上传不同的资源类型(图片、音频和视频),上传后调用第三方接口进行机审,要求:尽可能少用 if else 、易维护、易扩展和增加策略后不需要修改客户端代码。
3.2 if else 实现
业务实现代码:
public interface AudioAuditService {
void audit(Integer mediaType);
}
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class AudioAuditServiceImpl implements AudioAuditService {
public void audit(Integer mediaType) {
log.info("## audit param mediaType:{}", mediaType);
if (mediaType == 1) {
// 业务实现简略
System.out.println("视频机审, 调用腾讯AI机审接口");
} else if (mediaType == 2) {
// 业务实现简略
System.out.println("音频机审, 调用腾讯AI机审接口");
} else if (mediaType == 3) {
// 业务实现简略
System.out.println("图片机审, 调用腾讯AI机审接口");
}
}
}
客户端代码:
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class AudioAuditServiceImpl implements AudioAuditService {
public void audit(Integer mediaType) {
log.info("## audit param mediaType:{}", mediaType);
if (mediaType == 1) {
// 业务实现简略
System.out.println("视频机审, 调用腾讯AI机审接口");
} else if (mediaType == 2) {
// 业务实现简略
System.out.println("音频机审, 调用腾讯AI机审接口");
} else if (mediaType == 3) {
// 业务实现简略
System.out.println("图片机审, 调用腾讯AI机审接口");
}
}
}
使用postman模拟请求:
执行结果截图:
3.3 工厂模式 + 策略模式实现
策略类:
public interface AiAuditStrategy {
default void audit() {
throw new RuntimeException("此资源类型没有AI审核!");
}
}
工厂类:
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class AiAuditStrategyFactory {
// 使用ConcurrentHashMap管理所有的策略,避免并发请求产生线程安全问题
private static Map<Integer, AiAuditStrategy> map = new ConcurrentHashMap<>();
public static AiAuditStrategy getMediaType(Integer type) {
return map.get(type);
}
public static void register(Integer type, AiAuditStrategy strategy) {
map.put(type, strategy);
}
}
以下策略实现类均通过 Spring 的 InitializingBean 注册策略类
视频策略实现:
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
@Service
public class VideoAiAuditStrategy implements AiAuditStrategy, InitializingBean {
@Override
public void afterPropertiesSet() {
AiAuditStrategyFactory.register(1, this);
}
@Override
public void audit() {
// 业务实现简略
System.out.println("策略模式-视频机审, 调用腾讯AI机审接口");
}
}
音频策略实现:
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
@Service
public class AudioAiAuditStrategy implements AiAuditStrategy, InitializingBean {
@Override
public void afterPropertiesSet() {
AiAuditStrategyFactory.register(2, this);
}
@Override
public void audit() {
// 业务实现简略
System.out.println("策略模式-音频机审, 调用腾讯AI机审接口");
}
}
图片策略实现:
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
@Service
public class ImageAiAuditStrategy implements AiAuditStrategy, InitializingBean {
@Override
public void afterPropertiesSet() {
AiAuditStrategyFactory.register(3, this);
}
@Override
public void audit() {
// 业务实现简略
System.out.println("策略模式-图片机审, 调用腾讯AI机审接口");
}
}
客户端代码:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/media-resources")
public class MediaResourcesController {
@Autowired
private AudioAuditService audioAuditService ;
@PostMapping("/audit2")
public String audit2(@RequestParam Integer mediaType) {
AiAuditStrategyFactory.getMediaType(mediaType).audit();
return "OKK";
}
}
使用postman模拟请求:
执行结果截图:
工厂加策略模式完美实现上述需求,消除 if else 、易维护、易扩展、增加策略后不需要修改客户端代码,直接添加策略类即可。
– 欢迎点赞、关注、转发、收藏【技术咖啡馆C】,各大平台同名。
- 上一篇: 每天一个 Python 库:httpx异步请求,让接口测试飞起来
- 下一篇:已经是最后一篇了
猜你喜欢
- 2025-07-10 Vue3+Django4全新技术实战全栈项目|高清完结
- 2025-07-10 每天一个 Python 库:httpx异步请求,让接口测试飞起来
- 2025-07-10 如何高效实现API接口的自动化测试?
- 最近发表
-
- Vue3+Django4全新技术实战全栈项目|高清完结
- 工厂模式+策略模式消除 if else 实战
- 每天一个 Python 库:httpx异步请求,让接口测试飞起来
- 如何高效实现API接口的自动化测试?
- 前端工程化:从“手忙脚乱”到“从容协作”的进化记
- 使用C#创建服务端Web API(c#开发web服务器)
- SpringBoot之旅第四篇-web开发(springboot做web项目)
- 一文读懂SpringMVC(一文读懂新型政策性金融工具)
- Rust Web编程:第十二章 在 Rocket 中重新创建我们的应用程序
- Apache Druid 数据摄取——本地数据和kafka流式数据 一篇文章看懂
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)
- mysql数据库面试题 (57)