本文最后更新于86 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com
工厂模式 + 策略模式解决的核心问题
1. 解耦客户端与具体策略 客户端只需通过工厂获取策略接口,无需知道具体策略类的细节(如类名、构造参数),符合 “依赖倒置原则”。
2. 封装复杂的创建逻辑 策略的创建可能涉及参数校验、资源初始化(如数据库连接)、配置读取等逻辑,这些代码被集中封装在工厂中,避免重复。
3. 支持动态切换策略 通过工厂的 “类型参数” 或 “配置”,可以在运行时动态选择策略(如根据用户选择切换支付方式),无需修改客户端代码。
4. 符合开闭原则 新增策略时,只需添加新的策略类和工厂的创建逻辑(如在工厂中注册新策略类型),无需修改现有客户端代码,扩展性强。
工厂模式 + 策略模式实战
3.1 需求
有个后台管理系统,可以上传不同的资源类型(图片、音频和视频),上传后调用第三方接口进行机审,要求:尽可能少用 if else 、易维护、易扩展和增加策略后不需要修改客户端代码。
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 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("/audit")
public String audit(@RequestParam Integer mediaType) {
audioAuditService .audit(mediaType);
return "OK";
}
}


工厂模式 + 策略模式实现
策略类:
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 、易维护、易扩展、增加策略后不需要修改客户端代码,直接添加策略类即可。
工厂模式














