Spring通过Bean的name实现策略模式
迪丽瓦拉
2025-05-29 04:11:02
0

什么是策略模式?
如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。简单理解就是用策略模式替换掉if-else,让代码高内聚低耦合。不同的策略去做不同的事,每个策略之前相互不影响,提高代码的可读性。
策略模式:
优点:
1、算法可以自由切换。
2、避免使用多重条件判断。
3、扩展性良好
缺点:
1、策略类会增多。(我个人觉得不算事缺点吧。人尽其才,物尽其用。)
2、所有策略类都需要对外暴露。(这个才算是缺点,因为我只需要我想要的策略,你把其它我不想要策略都暴露出来了。)
常见的策略模式:Map map = new HashMap<>();这里的Map是策略接口,HashMap是具体实现的策略。Map map = new new TreeMap<>();

场景

假设我不同端的用户和密码都不一样,并且存放到不同的数据库表中,那么按照以前的方法就是通过if-else判断是否是其中的一个端,然后执行代码块。现在我们可以通过策略模式,让前端去调具体端的接口,比如我是web端,那么我前端就传一个web端的具体策略名称参数给后端,后端通过Spring的Bean name获取到具体策略的名称,实现具体的业务,然后把结果返回给前端。这样说可能不太容易理解。

定义策略接口

/*** 1. 新增策略接口。* 应用场景:多端登录,不同的端使用不同的数据库,所以执行不同的策略。*/
public interface Strategy {//2. 定义策略抽象方法(返回类型是T,让你的接口更加通用化!这里的参数你也可以使用String ... str表示传递多个String类型的参数。但是参数嘛,肯定具体的好点。否则可能就需要强转。)T login(String username,String password);
}

实现策略接口

web端

/*** 3.实现web登录策略*/
@Component("webLogin")
public class WebStrategyImpl implements Strategy {@Overridepublic WebTokenInfo login(String username, String password) {//查询web端的数据库,判断用户名和密码是否正确。//正确则返回web端的信息给前端WebTokenInfo webTokenInfo = new WebTokenInfo();webTokenInfo.setWebToken("web端的token");webTokenInfo.setWebUserId(1);return webTokenInfo;}
}

MiniApps端

/*** 3.实现小程序登录策略*/
@Component("miniAppsLogin")
public class MiniAppsStrategyImpl implements Strategy {@Overridepublic MiniAppsTokenInfo login(String username, String password) {//查询web端的数据库,判断用户名和密码是否正确。//正确则返回web端的信息给前端MiniAppsTokenInfo miniAppsTokenInfo = new MiniAppsTokenInfo();miniAppsTokenInfo.setMiniAppsToken("小程序端的token");miniAppsTokenInfo.setMiniAppsUserId(2);return miniAppsTokenInfo;}
}

根据Spring的Bean name去获取前端传递过来的具体策略参数调用具体的策略

/*** 4.根据前端传的bean的名字去执行具体的策略*/
@Component
public class ExecuteStrategy {//strategy就是@Component("name")的name,返回的是个Object更加通用,因为我们无需关注返回对象是什么,早在实现具体的策略的时候我们以及定义好了返回的对象,而Object是所有对象的基类(父类),需要关注Object具体是什么的只有前端!public Object executeStrategy(String strategy, String username, String password) {return  ((Strategy) ApplicationContextUtil.getBean(strategy)).login(username, password);}
}

Controller接收前端传递的策略参数以及登录接口参数

/*** 5.策略模式登录接口,实现多端登录*/
@RestController
@RequestMapping("strategy")
public class StrategyController {@Autowiredprivate ExecuteStrategy executeStrategy;/*** 登录接口* @param strategy 策略名称,即:XXXStrategyImpl的@Component("name")的name。* @param username 用户名(这里是为了策略而策略,所以假设用户名不同端存在不同的数据库中)* @param password 用户密码(这里是为了策略而策略,所以假设密码不同端存在不同的数据库中)*/@GetMapping("{strategy}")//这样写就可以让前端以为调不同的接口,实际上在后端是同一个接口,调的是impl的bean name实现类public Object login(@PathVariable String strategy, @RequestParam("username") String username,@RequestParam("password") String password){//根据前端传递的strategy策略参数,通过Spring的Bean的name去执行具体的策略。return this.executeStrategy.executeStrategy(strategy,username,password);}
}

其它

ApplicationContextUtil工具类

/*** 获取Bean*/
@Component
public class ApplicationContextUtil implements ApplicationContextAware {//构造函数私有化,防止其它人实例化该对象private ApplicationContextUtil(){}private static ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {ApplicationContextUtil.applicationContext = applicationContext;}//获取applicationContext(一般情况下用户数。因为我们暂时只需要获取bean就不需要获取其它内容了,而获取bean直接调用下面的方法即可。)public static ApplicationContext getApplicationContext() {return applicationContext;}//通过name获取 Bean.(推荐,因为bean的name是唯一的,出现重名的bean启动会报错。)public static Object getBean(String name) {return getApplicationContext().getBean(name);}//通过class获取Bean.(确保bean的name不会重复。因为可能会出现在不同包的同名bean导致获取到2个实例)public static  T getBean(Class clazz) {return getApplicationContext().getBean(clazz);}//通过name,以及Clazz返回指定的Bean(这个是最稳妥的)public static  T getBean(String name, Class clazz) {return getApplicationContext().getBean(name, clazz);}}

MiniAppsTokenInfo小程序返回vo,这个就是上面说的,由于策略接口返回的是个泛型T,我们已经在具体的策略里面定义好了返回类即可。

/*** web端token存储的信息*/
@Data
public class MiniAppsTokenInfo {private String miniAppsToken; //小程序端的tokenprivate Integer miniAppsUserId; //小程序端的用户id
}

WebTokenInfo web端返回vo(同上)

/*** web端token存储的信息*/
@Data
public class WebTokenInfo {private String webToken; //web端的tokenprivate Integer webUserId; //web端的用户id
}

模拟前端调用策略

调用web端的登录策略
在这里插入图片描述
调用小程序端的登录策略
在这里插入图片描述
调用没有的策略,就会抛出异常。
在这里插入图片描述
这里只是模拟,不要纠结为什么在url穿用户名和密码。

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
A.机器学习入门算法(三):基... 机器学习算法(三):K近邻(k-nearest neigh...
数字温湿度传感器DHT11模块... 模块实例https://blog.csdn.net/qq_38393591/article/deta...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
Redis 所有支持的数据结构... Redis 是一种开源的基于键值对存储的 NoSQL 数据库,支持多种数据结构。以下是...
win下pytorch安装—c... 安装目录一、cuda安装1.1、cuda版本选择1.2、下载安装二、cudnn安装三、pytorch...
MySQL基础-多表查询 文章目录MySQL基础-多表查询一、案例及引入1、基础概念2、笛卡尔积的理解二、多表查询的分类1、等...
keil调试专题篇 调试的前提是需要连接调试器比如STLINK。 然后点击菜单或者快捷图标均可进入调试模式。 如果前面...
MATLAB | 全网最详细网... 一篇超超超长,超超超全面网络图绘制教程,本篇基本能讲清楚所有绘制要点&#...
IHome主页 - 让你的浏览... 随着互联网的发展,人们越来越离不开浏览器了。每天上班、学习、娱乐,浏览器...
TCP 协议 一、TCP 协议概念 TCP即传输控制协议(Transmission Control ...
营业执照的经营范围有哪些 营业执照的经营范围有哪些 经营范围是指企业可以从事的生产经营与服务项目,是进行公司注册...
C++ 可变体(variant... 一、可变体(variant) 基础用法 Union的问题: 无法知道当前使用的类型是什...
血压计语音芯片,电子医疗设备声... 语音电子血压计是带有语音提示功能的电子血压计,测量前至测量结果全程语音播报࿰...
MySQL OCP888题解0... 文章目录1、原题1.1、英文原题1.2、答案2、题目解析2.1、题干解析2.2、选项解析3、知识点3...
【2023-Pytorch-检... (肆十二想说的一些话)Yolo这个系列我们已经更新了大概一年的时间,现在基本的流程也走走通了,包含数...
实战项目:保险行业用户分类 这里写目录标题1、项目介绍1.1 行业背景1.2 数据介绍2、代码实现导入数据探索数据处理列标签名异...
记录--我在前端干工地(thr... 这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前段时间接触了Th...
43 openEuler搭建A... 文章目录43 openEuler搭建Apache服务器-配置文件说明和管理模块43.1 配置文件说明...