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穿用户名和密码。

相关内容

热门资讯

AI做攻略、“双向奔赴”……国... 本文转自:人民网人民网记者 许维娜今年国庆假期,AI(人工智能)成了不少年轻人的“旅行搭子”。行前做...
合肥的这个“梗”, 翻篇了 社交平台的评论区,曾长期流传一句专属于合肥的黑色幽默。有人问合肥哪里好玩,本地网友半开玩笑地回复:合...
7万+旅游中高层都在的群,今天... 做旅游这行,资源卡位、渠道互通、项目落地——往往就差一个“对的机会”。我们的行业社群已聚集70,00...
一场帐篷音乐节,如何让井研从“... 帐篷音乐节现场封面新闻记者 周洪攀10月的研溪湿地,晚风里裹着柑橘的清甜与民谣的回响。夜幕降临,10...
白鹤翩翩落星愿,上海迪士尼度假... 10月9日,世界候鸟日前夕,上海迪士尼度假区星愿公园的湖风里多了一分白鹤的灵动。三座白鹤雕塑正式揭幕...
成都锦江边赏初秋枫叶飘飘 目前,成都锦江边国华街枫叶树红了。近年来,国华街附近的几条街都栽种了红枫树,是城区较集中看枫叶的点位...
GBTA:商务旅行正在复苏,但... 亚太正在成为全球商务旅行增长的重要引擎。在经历疫情后的快速反弹之后,全球商务旅行正在进入一个新的增长...
从景区焕新到节赛引流 邹城双节... 齐鲁网·闪电新闻10月9日讯 中秋、国庆“双节”假期,邹城市文化和旅游局提前谋划、周密部署,立足自身...
江山如此多娇 且看石楼今朝 金秋十月,黄河岸畔秋意盎然,丰收盛会喜迎国庆。本次石楼国庆文旅活动以“江山如此多娇,且看石楼今朝”为...
海南国庆假期接待游客475.4... 2026年国庆假期,海南接待游客475.40万人次,较2025年增长13.1%,较2024年增长15...