Java设计模式(五)策略模式-在SpringBoot项目中的实际应用

article/2025/10/4 15:20:21

文章目录

        • 什么是策略模式
          • 优点
          • 缺点
          • 使用场景
          • 结构图
        • 策略模式的简单示例
        • 策略模式的项目实战
          • 场景
          • 实现
        • 小结

什么是策略模式

官话:策略模式(Strategy Pattern): 定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换,策略模式让算法独立于使用它的客户而变化。

简单理解就是,针对不同的场景,使用不同的策略进行处理;

优点
  1. 算法可以自由切换。
  2. 避免使用多重条件判断。
  3. 扩展性良好。
缺点
  1. 策略类会增多。
  2. 所有策略类都需要对外暴露。
使用场景
  1. 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
  2. 一个系统需要动态地在几种算法中选择一种。
  3. 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
结构图

u=1524172280,2918452747&fm=253&fmt=auto&app=138&f=PNG

策略模式的简单示例

场景:最近太热了,想要降降温,有什么办法呢

首先,定义一个降温策略的接口

public interface CoolingStrategy {/*** 处理方式*/void handle();}

定义3种降温策略;实现策略接口

public class IceCoolingStrategy implements CoolingStrategy {@Overridepublic void handle() {System.out.println("使用冰块降温");}
}
public class FanCoolingStrategy implements CoolingStrategy {@Overridepublic void handle() {System.out.println("使用风扇降温");}
}
public class AirConditionerCoolingStrategy implements CoolingStrategy {@Overridepublic void handle() {System.out.println("使用空调降温");}
}

定义一个降温策略的上下文

public class CoolingStrategyContext {private final CoolingStrategy strategy;public CoolingStrategyContext(CoolingStrategy strategy) {this.strategy = strategy;}public void coolingHandle() {strategy.handle();}}

测试

public class Main {public static void main(String[] args) {CoolingStrategyContext context = new CoolingStrategyContext(new FanCoolingStrategy());context.coolingHandle();context = new CoolingStrategyContext(new AirConditionerCoolingStrategy());context.coolingHandle();context = new CoolingStrategyContext(new IceCoolingStrategy());context.coolingHandle();}
}

运行结果:

使用风扇降温
使用空调降温
使用冰块降温

以上就是一个策略模式的简单实现

策略模式的项目实战

场景

以我自己在工作中遇到的场景为例,《企业微信会话存档》功能,获取各种格式的消息内容,进行解析并保存数据。这里只针对消息处理的功能模块,其他关于《企业微信会话存档》的功能,请参见会话存档-如何高性能存储海量聊天记录、企业微信会话存档-文件下载

企业微信会话聊天会产生如下多种消息,在SpringBoot项目中应该如何使用策略模式来完成消息的解析呢?

image-20220709145204889

获取会话内容 - API 看API内容,数据都是json格式。思考应该如何处理:

  1. 首先,既然要解析各种数据,而每种数据格式结构都不一样,那么就需要先根据每种消息格式定义各自的对象,然后根据不同的需求,将json格式处理成pojo对象;

  2. 根据场景,需要定义两个策略接口,一个是针对普通的文本格式消息的策略,另一个则是需要处理文件格式消息的策略;

  3. 定义策略处理上下文操作类,用于使用策略

  4. 每种消息,都会有一些相同的数据,比如发送人、接收人、消息类型等;根据消息类型的不同,使用 key-value 的方式,让调用者确定应该使用哪个策略来处理数据

因为格式太多,这里只使用两个格式作为例子

实现

两个策略接口

public interface Strategy {/*** 处理会话存档的内容** @param content json格式的消息内容* @return 结果*/<T> T handleContent(String content);
}
public interface MediaStrategy {/*** 处理会话存档媒体内容** @param msgData 消息内容*/<T> void handleMedia(T msgData);
}

策略的具体实现(伪代码)

@Component("link")
public class LinkStrategy implements Strategy {@Overridepublic LinkPO handleContent(String content) {// JSON 转换为具体对象LinkWrapDTO linkWrapDTO = JacksonUtils.json2Obj(content, LinkWrapDTO.class);// 将对象处理成业务需要的格式return Convert.convert(LinkPO.class, linkWrapDTO);}
}
@Component("image")
public class ImageStrategy implements Strategy, MediaStrategy {@Autowiredprivate IMsgFileService msgFileService;@Overridepublic ImagePO handleContent(String content) {// JSON 转换为具体对象ImageWrapDTO imageWrapDTO = JacksonUtils.json2Obj(content, ImageWrapDTO.class);// 将对象处理成业务需要的格式return Convert.convert(ImagePO.class,imageWrapDTO);}@Overridepublic <T> void handleMedia(T msgData) {// 将数据格式转换为具体实现的数据格式ImagePO imagePo = Convert.convert(ImagePO.class, msgData);// 调用文件服务,进一步处理文件msgFileService.newFileTask(imagePo.getImage().getSdkfileid(),imagePo.getMsgid() + ".jpg", imagePo.getMsgid(), imagePo.getSeq(),imagePo.getImage().getFilesize(), imagePo.getImage().getMd5sum(), MessageEnum.IMAGE);}
}

策略上下文

@Component
public class StrategyContext {@ResourceMap<String, Strategy> strategys = new ConcurrentHashMap<>();@ResourceMap<String, MediaStrategy> mediaStrategys = new ConcurrentHashMap<>();public Strategy getStrategy(String component) {return strategys.get(component);}public MediaStrategy getMediaStrategy(String component) {return mediaStrategys.get(component);}
}

调用者(伪代码)

public class MsgService {@Resourceprivate StrategyContext strategyContext;public void handlerMessage() {// 请求api获取消息的jsonjson = api();// 转为通用格式对象basePo = JsonUtils.json2Obj(json, BasePO.class);// 选取不同的策略Strategy strategy = strategyContext.getStrategy(basePo.getMsgType());// 进行处理strategy.handleContent(json);// 关于文件类消息的处理MediaStrategy mediaStrategy = strategyContext.getMediaStrategy(basePo.getMsgtype());if (null != mediaStrategy) {mediaStrategy.handleMedia(basePo);}}
}

以上就是策略模式的一种实现方式;

小结

从以上的例子很明显的可以看出,策略模式的灵活性;如果此时企业微信提供了一种新的消息格式,那么根本无需修改之前的代码,只需要再写一个新的类,实现消息处理策略的接口,重写处理方法即可;

了解策略模式的优点和缺点,再根据业务场景来判断是否需要使用策略模式


http://chatgpt.dhexx.cn/article/UQ0O4AAj.shtml

相关文章

java调用微信加密_java微信消息加解密

今天心血来潮就信手拈来学了下微信消息加解密的知识,忽然觉得微信真的好强大。可能在大部分项目微信消息的加解密都用不上,但是仍然不排除有使用到的情况,如涉及金钱方面的微信应用包括商城类、金融类还有其他安全级别要求很高的微信应用。针对这些情况我觉得还是有必要分享…

spring如何使用策略模式

这里使用登录做例子介绍如何实现登录的多种策略 上图是策略模式的基础模型。 context Context上下文角色&#xff0c;也叫Context封装角色&#xff0c;起承上启下的作用&#xff0c;屏蔽高层模块对策略、算法的直接访问&#xff0c;封装可能存在的变化。 Strategy 策略角色…

java设计模式实战-(反射+策略模式)

学完23种设计模式&#xff0c;相信很多同学都疑问&#xff0c;除了单例模式、工厂模式其他模式还有运用的场景吗&#xff1f; 现在这里就举一个例子。 首先策略模式需要先有了解&#xff0c;我们常用策略模式解决实际开发中的if else特别多的场景。但是在实际的开发中&#x…

Java23种设计模式之策略模式【普通写法以及spring中的写法】

目录 设计模式简介策略模式的简介普通写法案例基于注解式改造的案例优缺点策略模式的使用场景 设计模式简介 将设计者的思维融入大家的学习和工作中&#xff0c;更高层次的思考&#xff01; • 创建型模式&#xff1a; – 单例模式、工厂模式、抽象工厂模式、建造者模式、原型…

Java设计模式-策略模式(支付业务的优化)

一、什么情况下使用策略模式 功能类似的业务功能&#xff0c;避免创建多个接口&#xff0c;大量if else 判断逻辑&#xff0c;简化代码 二、我以支付为例&#xff08;支付方式有微信&#xff0c;支付宝支付&#xff09; 1、新建策略抽象类或者接口 public interface ThirdP…

java策略模式实战示例

现已放在gitee上,可以不下载直接参考一下即: https://gitee.com/zhang-xiao-xiang/zxx-pattern 日常碰到的业务概述 登录类型,支付类型,供应商渠道,不同等级会员享受的优惠券价格不一样,等等业务判断,大量if else导致拓展(侧重新增)极其困难,维护(侧重修改)自然是改起来头痛(…

【JAVA设计模式】策略模式

1.什么是策略模式&#xff1f; 策略模式是对算法的包装&#xff0c;是把使用算法的责任和算法本身分割开来&#xff0c;委派给不同的对象管理&#xff0c;相同的事情-----选择不用同方式 &#xff08;不同实现&#xff09;举例子&#xff0c;最终可以实现解决多重if判断问题。 …

java微信关注事件_java策略模式在接收微信事件推送上的具体应用

java策略模式&#xff0c;在我的认知中是根据不同选择执行不同的实现。通过if或者switch-case也能实现这种逻辑&#xff0c;但是代码冗余&#xff0c;可扩展性不强。 百度百科上的解释为策略模式作为一种软件设计模式&#xff0c;指对象有某个行为&#xff0c;但是在不同的场景…

Java设计模式之3种策略模式实现

一、什么是策略模式 所谓策略模式&#xff0c;就是定义了一组策略&#xff0c;分别封装在不同类中&#xff0c;每种策略都可以根据当前场景相互替换&#xff0c;从而使策略的变化可以独立于操作者。比如我们要去某个地方&#xff0c;会根据距离的不同来选择不同的出行方式&…

java8 策略模式_JAVA设计模式之策略模式

策略模式&#xff1a;在策略模式(Strategy Pattern)中&#xff0c;一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。 在策略模式中&#xff0c;我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对…

git如何提交代码

代码提交 代码提交一般有五个步骤&#xff1a; 1.查看目前代码的修改状态 2.查看代码修改内容 3.暂存需要提交的文件 4.提交已暂存的文件 5.同步到服务器 1. 查看目前代码的修改状态 提交代码之前&#xff0c;首先应该检查目前所做的修改&#xff0c;运行git status命令 a)…

修改git提交时间

问题描述&#xff1a; 修改git提交记录的时间 git脚本&#xff1a; 此方法使用github上的开源工具完成。感谢无私的奉献者&#xff01; 操作步骤&#xff1a; github上下载文件 解压文件夹&#xff0c;把git-redate文件置于git安装目录的\mingw64\libexec\git-core文件夹…

git提交时常用命令

git提交时常用命令 一、git命令 -- 本地仓库与远程仓库建立链接 git init &#xff08;初始化本地仓库&#xff09; git remote add origin 远程仓库网址 git remote -v (查看远程仓库) git remote rm origin (删除远程分支)-- checkout多种用法 git checkout 文件名 &#…

git提交分支

1. git提交分支相关 在本地新建分支&#xff0c;保证和远程分支一样 git checkout -b 分支名如果分支已存在&#xff0c;只需要切换的话 git checkout 分支名提交前先把代码拉下来更新一下&#xff0c;确保不会覆盖别人的代码 git pull origin 远程分支(如果有)解决冲突 git …

Git 的提交

1 提交对象 理解Git分支&#xff0c;就需要了解提交及在提交过程中产生的提交对象&#xff08;commit object&#xff09;。在进行提交时Git会存储一个提交对象&#xff0c;其中包含一个指针&#xff0c;它指向此次提交时暂存内容的快照。除此之外&#xff0c;提交对象中还包含…

git代码提交

代码提交 代码提交一般有五个步骤&#xff1a; 1.查看目前代码的修改状态 2.查看代码修改内容 3.暂存需要提交的文件 4.提交已暂存的文件 5.同步到服务器 1. 查看目前代码的修改状态 提交代码之前&#xff0c;首先应该检查目前所做的修改&#xff0c;运行git status命令 a…

【git提交】流程

1- git提交&#xff08;分支合并&#xff09;操作流程&#xff1a; git 提交代码到自己的分支&#xff0c;并合并到主分支的完整流程 分支 sml &#xff0c; 主分支&#xff0c; master 分支msl上操作 git status git add . git commit -m ‘xxxxxx’ git pull origin master…

git提交规范,规范自己的提交标准

为了规范我的git提交内容&#xff0c;提交的时候commit -m “备注的信息”&#xff0c;但是每个人的备注信息千奇百怪&#xff0c;为了统一&#xff0c;我们进行了git的规范。 首先要全局安装commitizen npm i -g commitizen4.2.4然后安装插件 npm i cz-customizable6.3.0…

git提交常用命令

git 安装 1.在终端&#xff0c;检查git是否安装 git --version 2.没有安装的话&#xff0c;去git官网&#xff0c;下载git 3.安装后&#xff0c;在终端&#xff0c;检查git是否安装 4设置用户名和邮件地址&#xff08;最好和github的用户名/邮箱保持一致 git config -…

Git 提交规范

1. 背景 Git 是目前世界上最先进的分布式版本控制系统&#xff0c;在我们平时的项目开发中已经广泛使用。而当我们使用Git提交代码时&#xff0c;都需要写Commit Message提交说明才能够正常提交。 git commit -m "提交"然而&#xff0c;我们平时在编写提交说明时&a…