设计模式学习笔记-----抽象策略模式
抽象策略模式由五个核心组件组成
策略接口
定义所有策略的统一规范,是策略模式的 "契约"
mark()
:策略的唯一标识(类似字典的 key),默认返回 null,需具体策略实现类重写(如InterviewSubjectHandler
返回面试题类型标识)。patternMatchMark()
:策略的模糊匹配标识(支持正则),用于复杂场景下的模式匹配(非必需实现)。execute(REQUEST)
:无返回值的策略执行方法(默认空实现,按需重写)。executeResp(REQUEST)
:有返回值的策略执行方法(默认返回 null,按需重写)。
/*** 策略执行抽象*/
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()
(有返回值)方法,简化 "查找 + 执行" 的调用流程。
/*** 策略选择器*/
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);}@Overridepublic 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
实例,简化了策略模式的使用成本。
/*** 设计模式自动装配*/
@ImportAutoConfiguration(ApplicationBaseAutoConfiguration.class)
@Configuration
public class DesignPatternAutoConfiguration {/*** 策略模式选择器*/@Beanpublic AbstractStrategyChoose abstractStrategyChoose() {return new AbstractStrategyChoose();}}
策略模板类
作为策略的 "中间层",封装通用逻辑,避免具体策略类重复编码(结合了模板模式思想)。
通过抽象类提取共性逻辑,具体策略类只需关注自身特有的业务逻辑
@Component
public abstract class AbstractQuestionAddAndGetTemplate implements AbstractExecuteStrategy<QuestionInfoDTO, QuestionInfoVO> {@Resourceprivate 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();}}
具体策略类
策略模式的 "具体实现者",负责特定场景的业务逻辑。
@Component
public class InterviewSubjectHandler extends AbstractQuestionAddAndGetTemplate {@Resourceprivate QuestionInterviewDao questionInterviewDao;@Overridepublic String mark() {return QuestionInfoTypeEnum.INTERVIEW.getDesc();}@Overridepublic 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);}@Overridepublic 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 自动配置、模板类复用逻辑的组合设计,实现了策略的 "定义 - 注册 - 选择 - 执行" 全流程自动化,既保证了业务逻辑的解耦,又提供了极高的扩展性和灵活性,非常适合业务场景多变、需要频繁新增策略的系统(如多类型题目处理场景)。