策略模式【结合Spring框架实践】

Hello!~大家好啊,很高兴我们又见面了,今天我们一起学习设计模式–【策略模式】

初次对此模式不懂的,或者想偷懒的,我强烈建议大家跟着我的一起把概念和代码一起敲一遍!~为啥子??因为我就是这样学会的,哈哈哈!

1.首先我们看下此模式的整体UML

selector:选择器又叫做上下文context,【作用】通过不同的标识从而获取对应的策略实例(这是很关键的一个点,你细品~)

抽象策略: 如图所示,这是策略模式的顶层接口【就相当于领导~干运筹帷幄的】

策略实例 n:封装不同算法业务的实例对象,【就是特么真正干活的~!比如俺们码农】

在这里插入图片描述

2.案例实现

我们一个实际的案例进行实操,掌握这看起来高大上的策略模式,也是后面若你要面试,也能吹牛逼啊~

案例:

比如我们要统计餐厅的人流量数据做统计,统计的时间维度:一周和一个月,我们用策略模式咋实现呢? 我们往下看

实现需求分析:

在这里插入图片描述

  1. 前置设计:
    1. 我们定义常量标识策略的类型,
    2. 使用者调用时可通过常量获取对应的策略实例
  2. 策略设计
    1. 策略实例: 创建两个Bean实例: 周维度 &&月维度,并实现其中对应的算法和业务
    2. 抽象策略:通常我们定义一个通用的接口或者抽象方法,为啥???为了让外部能够访问啊!否则不是闭关锁国了嘛!~~
  3. 选择器设计: 这块就是挺重要的啦,我们通常采用MAP来存储数据,这样调用者就可以通过策略标识获取对应的策略实例

注意:

对于第三点可以是一道面试题:请问你怎么将策略的Bean注入到MAP中的?(不看答案,别心里好家伙,思考思考~哈哈)

也许你的第一反应:

我就直接将Bean对应的Class写死在``MAP中,然后通过applicationContext.getBaen()`获取其实例,这是最简单粗暴的!(也一看就是**菜鸡写法**哈哈哈)

若是这样回答,面试官肯定会问,这个通过写死的方法,那么下次我想增加其他维度的那不是要再次往Map中再添加,这麻烦先不说,也不符合开闭原则啊!~

你尴尬的扣了扣脚,微笑回答到:

是的,这是我一开始使用的,当时业务量不大,只考虑上面的两种情况,我就直接使用采取这种直接写死法,

但后面随着业务线的拓展,我也发现此中写法的弊端:

我的改进措施:(在Springboot的环境中)

1.通过解析注解来实现,给每个策略实例打上一个注解,我们业务是以周和月为维度进行常量标识的

2.过程: 在Springboot启动时,通过扩展点扫描抽象策略,获取它的策略实例

3.然后解析注解,放入MAP

这种就不用对原先代码就行逻辑代码改动,既符合开闭原则,又回到了面试官,爽哉!~

说了这么多,那关于代码我们怎么实现呢?–>耐心点,我们一起往下看

代码实现

1.抽象策略

package org.boyunv.strategy_pattern.handler;/*** <p>* 描述:  抽象策略    <br>* <p>* 需求信息: 【需求ID与需求标题】【客户名称】 <br>** @author aristo* @date 2024/1/23 19:07*/
public interface TimeDimensionBaseHandlerInterface {//此方法是留给不同策略实体实现不同策略的方法实现void  statistic();
}

2.【策略实体】

这里我们注册组件直接采用Spring框架的组件@Component进行注册即可

1.周统计维度

package org.boyunv.strategy_pattern.handler;import org.springframework.stereotype.Component;/*** <p>* 描述:  策略实体: 周统计维度$      <br>* <p>* 需求信息: 【需求ID与需求标题】【客户名称】 <br>** @author aristo* @date 2024/1/23 19:12*/
@Component("week")
public class StatisticByWeekHandler implements TimeDimensionBaseHandlerInterface{@Overridepublic void statistic() {//具体实现System.out.println("通过周统计维度实现统计数据");}
}

2.月统计维度

package org.boyunv.strategy_pattern.handler;import org.springframework.stereotype.Component;/*** <p>* 描述:  策略实体: 月统计维度$      <br>* <p>* 需求信息: 【需求ID与需求标题】【客户名称】 <br>** @author aristo* @date 2024/1/23 19:12*/
@Component("month")
public class StatisticByMonthHandler implements TimeDimensionBaseHandlerInterface{@Overridepublic void statistic() {System.out.println("通过月统计维度实现统计数据");}
}

3.选择器【Inevitable!】

看如下的代码,我们会发现他同样是个组件,@Component

@Resource:将我们注册的weekmonth组件注册进入MAP

package org.boyunv.strategy_pattern.selector;import org.boyunv.strategy_pattern.handler.TimeDimensionBaseHandlerInterface;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.Map;/*** 描述:  选择器,核心重点$      <br>* 需求信息: 【需求ID与需求标题】【客户名称】 <br>* @date 2024/1/23 19:26*/
@Component
public class StatisticSelector {//这就和我们上面的所说的:定义Map,并通过@Resource注解完成我们刚才week和month的组件注入(很关键的一步哦!~)@Resourceprivate Map<String, TimeDimensionBaseHandlerInterface> selectorMap;//下面根据类型选择策略public TimeDimensionBaseHandlerInterface select(String type){return selectorMap.get(type);}
}

4.我们进行测试

package org.boyunv.strategy_pattern.selector;import org.boyunv.strategy_pattern.handler.TimeDimensionBaseHandlerInterface;
import org.junit.Test;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.Map;/*** 描述:  选择器,核心重点$      <br>* 需求信息: 【需求ID与需求标题】【客户名称】 <br>* @date 2024/1/23 19:26*/
@Component
public class StatisticSelector {//这就和我们上面的所说的:定义Map,并通过@Resource注解完成我们刚才week和month的组件注入(很关键的一步哦!~)@Resourceprivate Map<String, TimeDimensionBaseHandlerInterface> selectorMap;//下面根据类型选择策略public TimeDimensionBaseHandlerInterface select(String type){return selectorMap.get(type);}public  void doInvoke(String type){TimeDimensionBaseHandlerInterface handler=select(type);handler.doStatistic();}@Testpublic void invoke(){this.doInvoke("week");this.doInvoke("month");}
}

完结:

通过上面的运行步骤,我们最中实现策略模式的周和月的策略实现

这里面的核心点,再次提醒下:

通过Spring获取接口的实现,并解析实现类上的注解的方式,可以在程序启动时动态的将策略注入到一个Map中,作为策略的容器。

使用时传入标识符(就是常量)就可以获取到对应的策略执行了。

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

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

相关文章

Netty篇章(1)—— 核心原理介绍

终于进入到Netty框架的环节了&#xff0c;前面介绍了大量的Java-NIO的内容&#xff0c;核心的内容Selector、Channel、Buffer、Reactor掌握了&#xff0c;那么学起来Netty也是水到渠成的事情。如果没有掌握前面的内容那么学Netty会非常吃力&#xff0c;下面讲解Netty核心原理与…

关于 LLM,你了解多少?

LLM定义 大语言模型&#xff08;LLM&#xff09;是一种基于大量文本数据训练的深度学习模型。它的主要功能是生成自然语言文本或理解语言文本的含义。这些模型可以处理多种自然语言任务&#xff0c;如文本分类、问答、对话等&#xff0c;是通向人工智能的一条重要途径。 LLM发…

美创荣登“2023大数据产业年度最具投资价值”榜单

近日&#xff0c;由上海市经济和信息化委员会、上海市科学技术委员会指导&#xff0c;数据猿和上海大数据联盟主办的“第六届金猿季&魔方论坛——大数据产业发展论坛”在沪隆重召开&#xff0c;并重磅揭晓《2023大数据产业年度最具投资价值》榜单。 美创科技凭借在数据安全…

k8s-kubectl常用命令

一、基础命令 1.1 get 查询集群所有资源的详细信息&#xff0c;resource包括集群节点、运行的Pod、Deployment、Service等。 1.1.1 查询Pod kubectl get po -o wid 1.1.2 查询所有NameSpace kubectl get namespace 1.1.3 查询NameSpace下Pod kubectl get po --all-namespaces…

JAVA 学习 面试(二)多线程篇

Java多线程 线程池 线程池原理 创建方式&#xff1a;newFixedThreadPool (固定数目线程的线程池)、newCachedThreadPool(可缓存线程的线程池)、newSingleThreadExecutor(单线程的线程池)、newScheduledThreadPool(定时及周期执行的线程池)、new ThreadPoolExecutor() &#x…

Elasticsearch 常用信息

简述 本文针对 Elasticsearch&#xff08;简称ES&#xff09;集群6.x版本出现故障时&#xff0c;可通过提供的命令进行排查。 1、集群健康状态 集群健康状态状态说明red不是所有的主要分片都可用。表示该集群中存在不可用的主分片。可以理解为某个或者某几个索引存在主分片丢失…

AI破局之路:一名猎头高管的AI自学之旅——公众号

AI破局之路&#xff1a;一名猎头高管的AI自学之旅——公众号。 我是周知&#xff0c;有8年猎头行业经验深耕各类顶级科技企业。 2023年&#xff0c;应该有很多同行离开这个行业吧. 毕竟我们面临着前所未有的挑战。猎头行业的每一个参与者&#xff0c;无论是初入职场的猎头新人、…

2024最新科普:文件加密软件功能大盘点

随着信息化时代的到来&#xff0c;数据安全问题越来越受到人们的关注。 文件加密作为一种重要的数据保护手段&#xff0c;被广泛应用于企业和个人用户中。 本文将对文件加密软件的功能进行大盘点&#xff0c;帮助大家了解这一安全领域的知识。 一、文件加密软件的定义 文件加…

【STM32】USB程序烧录需要重新上电 软件复位方法

文章目录 一、问题二、解决思路2.1 直接插拔USB2.2 给芯片复位 三、解决方法3.1 别人的解决方法3.2 在下载界面进行设置 一、问题 最近学习STM32的USB功能&#xff0c;主要是想要使用虚拟串口功能&#xff08;VCP&#xff09;&#xff0c;发现每次烧录之后都需要重新上电才可以…

FRRouting学习(一) 配置日志文件

以配置isis event事件日志为例 1、在配置之前&#xff0c;/var/log/frr路径下是没有文件的&#xff1a; 2、在vtysh config之下输入&#xff1a;log file /var/log/frr/isisd.log debugging 后面的debugging表示日志级别&#xff0c;可以根据自己修改 3、配置好了之后&#xf…

Operation

contents 服务器一、相关概念1.1 云服务器与实例1.2 关于域名解析延时与80端口1.3 关于备案1.4 关于SSL证书1.5 关于SSL证书的签发1.6 关于SSL证书的部署1.7 关于LNMP和LAMP1.8 关于bt面板 二、单服务器单一级域名多网站2.1 创建多个二级域名2.2 解析二级域名绑定到服务器上2.3…

基于SpringBoot Vue求职招聘系统

大家好✌&#xff01;我是Dwzun。很高兴你能来阅读我&#xff0c;我会陆续更新Java后端、前端、数据库、项目案例等相关知识点总结&#xff0c;还为大家分享优质的实战项目&#xff0c;本人在Java项目开发领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#x…

工业设备管理系统:助力企业实现数字化转型

随着工业4.0和智能制造的快速发展&#xff0c;数字化转型已成为企业提升竞争力、适应市场变化的必然选择。工业设备管理系统作为数字化转型的关键组成部分&#xff0c;能够为企业提供实时监控、数据分析、预警和远程控制等功能&#xff0c;助力企业实现数字化转型的目标。 一、…

debian12.4配置

文章目录 debian12.4配置概述笔记将非root用户添加到sudo组更换国内源配置ssh的客户端访问关闭屏保END debian12.4配置 概述 在虚拟机中装了一个debian12.4, 想配置ssh客户端连接, 出了问题. 配置乱了, 还好长了个心眼, 做了快照. 发现2个问题: debian12.4默认安装完, 有ss…

mysql生成最近24小时整点时间临时表

文章目录 生成最近24小时整点生成最近30天生成最近12个月 生成最近24小时整点 SELECT-- 每向下推1行, i比上次减去1b.*, i.*,DATE_FORMAT( DATE_SUB( NOW(), INTERVAL ( -( i : i - 1 ) ) HOUR ), %Y-%m-%d %H:00 ) AS time FROM-- 目的是生成12行数据( SELECTa FROM( SELECT…

LINUX服务之YUM仓库

1. YUM概述 YUM基于RPM包构建的软件更新机制 可以自动解决依赖关系 所有软件包由集中的YUM软件仓库提供 YUM支持软件源 搭建yum支持的的软件源主要有以下三种&#xff1a; 本地yum&#xff1a;file&#xff1a;//… 网络yum&#xff0c;又分为HTTP服务器&#xff1a;http…

UE5.2、CesiumForUnreal实现加载GeoJson绘制单面

文章目录 前言一、实现目标二、实现过程1.实现原理2.数据读取3.三角剖分3.具体代码 4.蓝图测试 前言 UE5、CesiumForUnreal实现加载GeoJson绘制单面&#xff08;Polygon&#xff09;功能&#xff08;StaticMesh方式&#xff09; 一、实现目标 通过读取本地的Geojson数据&…

IP地址组成

一、简介 ​ IP地址由四段组成&#xff0c;每个字段是一个字节&#xff0c;即4个字节、 每个字节有8位&#xff0c;最大值是255(256&#xff1a;0~255)&#xff0c;是全世界范围是唯一的 32 位&#xff08;4个字节 * 8位&#xff09;的标识符。 ​ IP地址由两部分组成&#x…

电商模特危机!谷歌最新模型Tryon Diffusion一键试衣,线上购物被革命

目录 前言 摘要 方法 结果展示 多人试穿同一件衣服 同一个人试穿不同的衣服 交互式试穿演示 与最先进方法的比较 总结分析 前言 谷歌的新AI模型TryOnDiffusion&#xff0c;直接解决了AI换装的两大难题——既保留衣服细节&#xff0c;又能随意换姿势。…

通过curl访问k8s集群获取证书或token的方式

K8S安全控制框架主要由下面3个阶段进行控制&#xff0c;每一个阶段都支持插件方式&#xff0c;通过API Server配置来启用插件。 1. Authentication&#xff08;认证&#xff09; 2. Authorization&#xff08;授权&#xff09; 3. Admission Control&#xff08;准入控制&#…