抽象策略模式由五个核心组件组成
策略接口
定义所有策略的统一规范,是策略模式的 "契约"
mark()
:策略的唯一标识(类似字典的 key),默认返回 null,需具体策略实现类重写(如InterviewSubjectHandler
返回面试题类型标识)。patternMatchMark()
:策略的模糊匹配标识(支持正则),用于复杂场景下的模式匹配(非必需实现)。execute(REQUEST)
:无返回值的策略执行方法(默认空实现,按需重写)。executeResp(REQUEST)
:有返回值的策略执行方法(默认返回 null,按需重写)。
java
/**
* 策略执行抽象
*/
public interface AbstractExecuteStrategy<REQUEST, RESPONSE> {
/**
* 执行策略标识
*/
default String mark() {
return null;
}
/**
* 执行策略范匹配标识
*/
default String patternMatchMark() {
return null;
}
/**
* 执行策略
*
* @param requestParam 执行策略入参
*/
default void execute(REQUEST requestParam) {
}
/**
* 执行策略,带返回值
*
* @param requestParam 执行策略入参
* @return 执行策略后返回值
*/
default RESPONSE executeResp(REQUEST requestParam) {
return null;
}
}
所有方法均为default
(默认方法),允许策略实现类按需重写(无需实现所有方法),降低接口实现成本。
策略选择器
策略的 "管理者",负责策略的注册、查找和执行调度,是策略模式的核心上下文(Context)
- 策略注册 :实现
ApplicationListener
,在应用初始化时(onApplicationEvent
)从 Spring 容器中获取所有AbstractExecuteStrategy
实现类,存入abstractExecuteStrategyMap
(key 为mark()
,value 为策略实例),并校验mark
唯一性(避免冲突)。 - 策略查找 :
choose()
方法支持两种查找方式:- 精确匹配:通过
mark
直接从 map 中获取策略。 - 模糊匹配:当
predicateFlag=true
时,用patternMatchMark()
的正则匹配mark
,适合多标识对应同一策略的场景。
- 精确匹配:通过
- 策略执行 :提供
chooseAndExecute()
(无返回值)和chooseAndExecuteResp()
(有返回值)方法,简化 "查找 + 执行" 的调用流程。
java
/**
* 策略选择器
*/
public class AbstractStrategyChoose implements ApplicationListener<ApplicationInitializingEvent> {
/**
* 执行策略集合
*/
private final Map<String, AbstractExecuteStrategy> abstractExecuteStrategyMap = new HashMap<>();
/**
* 根据 mark 查询具体策略
*
* @param mark 策略标识
* @param predicateFlag 匹配范解析标识
* @return 实际执行策略
*/
public AbstractExecuteStrategy choose(String mark, Boolean predicateFlag) {
if (predicateFlag != null && predicateFlag) {
return abstractExecuteStrategyMap.values().stream()
.filter(each -> StringUtils.hasText(each.patternMatchMark()))
.filter(each -> Pattern.compile(each.patternMatchMark()).matcher(mark).matches())
.findFirst()
.orElseThrow(() -> new ServiceException("策略未定义"));
}
return Optional.ofNullable(abstractExecuteStrategyMap.get(mark))
.orElseThrow(() -> new ServiceException(String.format("[%s] 策略未定义", mark)));
}
/**
* 根据 mark 查询具体策略并执行
*
* @param mark 策略标识
* @param requestParam 执行策略入参
* @param <REQUEST> 执行策略入参范型
*/
public <REQUEST> void chooseAndExecute(String mark, REQUEST requestParam) {
AbstractExecuteStrategy executeStrategy = choose(mark, null);
executeStrategy.execute(requestParam);
}
/**
* 根据 mark 查询具体策略并执行
*
* @param mark 策略标识
* @param requestParam 执行策略入参
* @param predicateFlag 匹配范解析标识
* @param <REQUEST> 执行策略入参范型
*/
public <REQUEST> void chooseAndExecute(String mark, REQUEST requestParam, Boolean predicateFlag) {
AbstractExecuteStrategy executeStrategy = choose(mark, predicateFlag);
executeStrategy.execute(requestParam);
}
/**
* 根据 mark 查询具体策略并执行,带返回结果
*
* @param mark 策略标识
* @param requestParam 执行策略入参
* @param <REQUEST> 执行策略入参范型
* @param <RESPONSE> 执行策略出参范型
* @return
*/
public <REQUEST, RESPONSE> RESPONSE chooseAndExecuteResp(String mark, REQUEST requestParam) {
AbstractExecuteStrategy executeStrategy = choose(mark, null);
return (RESPONSE) executeStrategy.executeResp(requestParam);
}
@Override
public void onApplicationEvent(ApplicationInitializingEvent event) {
Map<String, AbstractExecuteStrategy> actual = ApplicationContextHolder.getBeansOfType(AbstractExecuteStrategy.class);
actual.forEach((beanName, bean) -> {
AbstractExecuteStrategy beanExist = abstractExecuteStrategyMap.get(bean.mark());
if (beanExist != null) {
throw new ServiceException(String.format("[%s] Duplicate execution policy", bean.mark()));
}
abstractExecuteStrategyMap.put(bean.mark(), bean);
});
}
}
自动配置类
整合 Spring 容器,将策略选择器AbstractStrategyChoose
注册为 Spring Bean,使其能被全局注入使用。通过 Spring 的自动配置机制,无需手动创建AbstractStrategyChoose
实例,简化了策略模式的使用成本。
java
/**
* 设计模式自动装配
*/
@ImportAutoConfiguration(ApplicationBaseAutoConfiguration.class)
@Configuration
public class DesignPatternAutoConfiguration {
/**
* 策略模式选择器
*/
@Bean
public AbstractStrategyChoose abstractStrategyChoose() {
return new AbstractStrategyChoose();
}
}
策略模板类
作为策略的 "中间层",封装通用逻辑,避免具体策略类重复编码(结合了模板模式思想)。
通过抽象类提取共性逻辑,具体策略类只需关注自身特有的业务逻辑
java
@Component
public abstract class AbstractQuestionAddAndGetTemplate implements AbstractExecuteStrategy<QuestionInfoDTO, QuestionInfoVO> {
@Resource
private QuestionInfoDao questionInfoDao;
protected QuestionInfoVO buildQuestionInfoVO(QuestionInfoDTO questionInfoDTO) {
QuestionInfo questionInfo = questionInfoDao.queryById(questionInfoDTO.getId());
return QuestionInfoVO.builder()
.id(questionInfo.getId())
.createdTime(questionInfo.getCreatedTime())
.createdBy(questionInfo.getCreatedBy())
.subjectDifficult(questionInfo.getSubjectDifficult())
.subjectParse(questionInfo.getSubjectParse())
.updateTime(questionInfo.getUpdateTime())
.updateBy(questionInfo.getUpdateBy())
.subjectType(questionInfo.getSubjectType())
.subjectName(questionInfo.getSubjectName())
.settleName(questionInfo.getSettleName())
.build();
}
}
具体策略类
策略模式的 "具体实现者",负责特定场景的业务逻辑。
java
@Component
public class InterviewSubjectHandler extends AbstractQuestionAddAndGetTemplate {
@Resource
private QuestionInterviewDao questionInterviewDao;
@Override
public String mark() {
return QuestionInfoTypeEnum.INTERVIEW.getDesc();
}
@Override
public void execute(QuestionInfoDTO requestParam) {
QuestionInterview questionInterview = QuestionInterview.builder()
.subjectId(Math.toIntExact(requestParam.getId()))
.createdBy(requestParam.getCreatedBy())
.subjectAnswer(requestParam.getSubjectAnswer())
.isDeleted(IsDeletedFlagEnum.UN_DELETED.getCode())
.createdTime(new Date())
.updateTime(new Date())
.build();
questionInterviewDao.insert(questionInterview);
}
@Override
public QuestionInfoVO executeResp(QuestionInfoDTO requestParam) {
QuestionInfoVO questionInfoVO = buildQuestionInfoVO(requestParam);
QuestionInterview questionInterview = questionInterviewDao.queryById(requestParam.getId());
questionInfoVO.setSubjectAnswer(questionInterview.getSubjectAnswer());
return questionInfoVO;
}
}
执行流程
- Spring 容器初始化时,
AbstractStrategyChoose
监听ApplicationInitializingEvent
事件。 - 从容器中扫描到
InterviewSubjectHandler
(实现了AbstractExecuteStrategy
),将其mark()
(面试题标识)作为 key,实例作为 value,存入abstractExecuteStrategyMap
。
- 当需要处理面试题时,调用
AbstractStrategyChoose.chooseAndExecute("面试题标识", requestParam)
。 - 选择器通过
mark
从 map 中找到InterviewSubjectHandler
实例,调用其execute()
方法执行新增逻辑。
总结
这套抽象策略模式通过接口定义规范 、选择器管理策略 、Spring 自动配置 、模板类复用逻辑的组合设计,实现了策略的 "定义 - 注册 - 选择 - 执行" 全流程自动化,既保证了业务逻辑的解耦,又提供了极高的扩展性和灵活性,非常适合业务场景多变、需要频繁新增策略的系统(如多类型题目处理场景)。