设计模式学习笔记-----抽象策略模式

抽象策略模式由五个核心组件组成

策略接口

定义所有策略的统一规范,是策略模式的 "契约"

  • 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 自动配置模板类复用逻辑的组合设计,实现了策略的 "定义 - 注册 - 选择 - 执行" 全流程自动化,既保证了业务逻辑的解耦,又提供了极高的扩展性和灵活性,非常适合业务场景多变、需要频繁新增策略的系统(如多类型题目处理场景)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/94668.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/94668.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ面试精讲 Day 30:RabbitMQ面试真题解析与答题技巧

【RabbitMQ面试精讲 Day 30】RabbitMQ面试真题解析与答题技巧 开篇&#xff1a;系列收官之作&#xff0c;直击面试核心 今天是“RabbitMQ面试精讲”系列的第30天&#xff0c;也是本系列的收官之作。经过前29天对RabbitMQ核心概念、高级特性、集群架构、性能调优与开发运维的系…

Coze Studio开源版:AI Agent开发平台的深度技术解析- 入门篇

Coze Studio开源版&#xff1a;AI Agent开发平台的深度技术解析 引言 在人工智能快速发展的今天&#xff0c;AI Agent&#xff08;智能体&#xff09;已成为连接大语言模型与实际应用场景的重要桥梁。然而&#xff0c;构建一个功能完整、性能稳定的AI Agent开发平台并非易事&am…

一文了解 DeepSeek 系列模型的演进与创新

近年来&#xff0c;DeepSeek 团队在大语言模型&#xff08;LLM&#xff09;领域持续发力&#xff0c;围绕模型架构、专家路由、推理效率、训练方法等方面不断优化&#xff0c;推出了一系列性能强劲的开源模型。本文对 DeepSeek 系列的关键论文进行了梳理&#xff0c;帮助大家快…

开源大模型本地部署

一、大模型 T5\BERT\GPT → Transformer的儿子→自注意力机制神经网络 大模型&#xff0c; Large Model&#xff0c;是指参数规模庞大、训练数据量巨大、具有强泛化能力的人工智能模型&#xff0c;典型代表如GPT、BERT、PaLM等。它们通常基于深度神经网络&#xff0c;特别是T…

DAY 57 经典时序预测模型1

知识点回顾 序列数据的处理&#xff1a; 处理非平稳性&#xff1a;n阶差分处理季节性&#xff1a;季节性差分自回归性无需处理 模型的选择 AR(p) 自回归模型&#xff1a;当前值受到过去p个值的影响MA(q) 移动平均模型&#xff1a;当前值收到短期冲击的影响&#xff0c;且冲击影…

贪吃蛇游戏(纯HTML)

一、游戏截图二、源码 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>离谱贪吃蛇</title>…

InnoDB详解2

InnoDB详解2一.行结构1.结构图2.InnoDB支持的数据行格式1&#xff09;查看当前数据库或表的行格式2&#xff09;指定行格式3&#xff09;DYNAMIC 格式的组成3.数据区存储真实数据方式4.行的额外(管理)信息区5.头信息区域1&#xff09;删除一行记录时在InnoDB内部执行的操作6.Nu…

Rust系统编程实战:驾驭内存安全、无畏并发与WASM跨平台开发

简介本文深入探讨Rust在系统编程领域的核心实战应用&#xff0c;通过代码示例解析其所有权机制如何保障内存安全&#xff0c;如何利用 fearless concurrency 构建高性能并发应用&#xff0c;并实践如何将Rust代码编译为WebAssembly&#xff08;WASM&#xff09;以突破性能瓶颈。…

JavaScript 基础入门:从概念解析到流程控制

文章目录1. JavaScript 核心认知1.1 浏览器与 JavaScript 的关系1.2 JavaScript 的三大核心组成1.3 JavaScript 引入1.3.1 内联脚本&#xff08;事件属性绑定&#xff09;1.3.2 内部脚本&#xff08;<script> 标签嵌入&#xff09;1.3.3 外部脚本&#xff08;独立 .js 文…

WebSocket简单了解

WebSocket 是一种计算机网络通信协议&#xff0c;它在客户端和服务器之间建立一个持久的、双向的通信通道。与传统的 HTTP 请求-响应模型不同&#xff0c;WebSocket 允许数据在客户端和服务器之间实时双向传输&#xff0c;因此非常适合需要即时交互的应用&#xff0c;如实时聊天…

【实时Linux实战系列】基于实时Linux的生物识别系统

在当今数字化时代&#xff0c;生物识别技术因其高安全性和便捷性而被广泛应用。生物识别系统通过识别个人的生物特征&#xff08;如面部、指纹等&#xff09;来验证身份&#xff0c;广泛应用于安全门禁、移动支付、智能设备解锁等领域。这些系统不仅提高了安全性&#xff0c;还…

汇智焕彩,聚势创新 - openKylin 2.0 SP2正式发布!

OpenAtom openKylin&#xff08;简称 “openKylin”&#xff09; 2.0 SP2版本正式发布&#xff01;本次版本更新在底层核心能力上&#xff0c;持续维护 6.6 稳定版内核&#xff0c;深度适配海光、飞腾、兆芯、龙芯等国产主流芯片&#xff0c;并积极推动 RISC-V 开放指令集架构生…

怎么评估高精度组合惯导的惯性导航价格?

内容概要高精度组合惯导系统的价格评估是一个需要综合考量多个关键因素的复杂过程。理解其成本构成&#xff0c;对于制定合理的采购预算和优化决策至关重要。评估的核心首先聚焦于IMU传感器价格&#xff0c;这是整个系统成本中最主要的组成部分之一。同时&#xff0c;选择可靠且…

深度学习开篇

首先我们要知道深度学习和机器学习的关系——深度学习(DL, Deep Learning)是机器学习(ML, Machine Learning)领域中一个新的研究方向。 深度学习简介 我理解的深度学习就通过多层感知器&#xff0c;对数据进行训练&#xff0c;可以达到非线性变换&#xff0c;如何可以提取非线性…

Typescript入门-interface讲解

对象成员语法形式1&#xff09;对象属性2&#xff09;对象的属性索引3&#xff09;对象的方法4&#xff09;函数5&#xff09;构造函数interface 的继承interface 继承 interfaceinterface 继承 typeinterface 继承 class接口合并interface 与 type 的异同interface 是对象的模…

数据结构青铜到王者第五话---LinkedList与链表(2)

目录 一、常见的链表题目练习&#xff08;续&#xff09; 1、链表的回文结构。 2、输入两个链表&#xff0c;找出它们的第一个公共结点。 3、给定一个链表&#xff0c;判断链表中是否有环。 4、给定一个链表&#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#…

Kafa面试经典题--Kafka为什么吞吐量大,速度快

这是一个非常核心的面试题和技术问题。Kafka 的高吞吐量和速度并非来自某一项“银弹”技术,而是其架构设计中一系列精巧决策共同作用的结果。 一、核心思想:最大化利用底层硬件资源 Kafka 速度快的根本原因是,它的设计哲学是 “尽可能地避免不必要的开销,并将硬件(尤其是…

Stream API 新玩法:从 teeing()到 mapMulti()

1. 背景&#xff1a;Stream API 的演进 自 Java 8 引入 Stream API 以来&#xff0c;Java 的集合处理方式发生了质变。开发者可以用声明式风格实现复杂的数据转换与聚合。然而&#xff0c;随着应用场景多样化&#xff0c;社区逐渐发现一些“尴尬空缺”&#xff1a; 聚合时&…

STM32G4 SVPWM VF开环强拖电机

目录一、STM32G4 SVPWM VF开环强拖电机1 SVPWM1.1 SVPWM技术简介1.2 基于零序分量注入的SVPWM算法的实现2. VF开环强拖电机3. VF启动电机实验现象附学习参考网址欢迎大家有问题评论交流 (* ^ ω ^)一、STM32G4 SVPWM VF开环强拖电机 1 SVPWM 1.1 SVPWM技术简介 SVPWM控制策略…

产品运营必备职场通用能力及提升攻略,一文说明白

在互联网行业蓬勃发展的当下&#xff0c;产品运营岗位成为了连接产品、用户与商业目标的关键纽带。从用户增长到活动策划&#xff0c;从数据分析到跨部门协作&#xff0c;产品运营人员需具备多元化技能&#xff0c;才能在激烈竞争中崭露头角。随着企业对精细化运营与数据驱动决…