网站首页 > 资源文章 正文
责任链模式
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。
这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会
把相同的请求传给下一个接收者,依此类推。
复制代码
需求
在公司流程处理业务中,有不同的处理流程节点,在不同的节点需要发送不同的短信,用来通知下一个节点的处置人。 1发起->2审核->3处置->4结果审核->完成,每个环节还可以有退回到上一个节点的功能,而且不同的地区还可能有其他的流程节点。一开始产品只提出审核和处置两个节点需要发送短信,因此一开始的代码是这样写的。
public class WarningSmsHandler {
public void sendSms() {
//处理发送短信逻辑
if(是否是审核完成) {
//查询处置人,设置短信内容,发送短信
} else if(是否是处置完成) {
//查询结果审核人,设置短信内容,发送短信
}
}
}
复制代码
随着时间推移,产品又提出需要在发起环节发送短信,通知审核人。这个时候可以选择修改原来的WarningSmsHandler类,这样现在实现起来是比较快的,但是这样也会给以后带来一些问题: 1、随着越来越多节点的短信发送需求,后面会不断的在这个类加代码,违反了单一职责原则。 2、以后加一个节点的短信,删除一个节点的短信,都需要改WarningSmsHandler类的代码,违背开闭原则。
所以必须思考下如何选择一个周全的方案,避免这些问题。 回到需求,短信发送是上一个节点发送给下一个节点,一般只发送给下一个节点的人。这里想到使用责任链模式,将各个节点发送短信的逻辑进行拆分,单一职责。
根据责任链模式实现该需求
1、定义统一请求类
@Data
public class WarningSmsHandlerRequest{
//通报id
private Long warningId;
//下一个通报状态
private WarningStateEnum nextWarningState;
//下一个通报处置人类型
private WarningHandleUnitEnum warningHandleUnitEnum;
//附加参数
private List<String> attachmentParam;
//短信模版id 有些短信厂商需要模版
private String templateId;
}
复制代码
2、定义统一处理结果类
@Data
public class WarningSmsHandlerResult {
//发送成功的手机号列表
private List<String> mobiles =new ArrayList<>();
//发送是否成功
private Boolean success;
}
复制代码
2、定义请求处理接口
/**
* 短信处理器接口
*/
public interface SmsHandler {
//当前接口是否支持处理
boolean support(WarningSmsHandlerRequest request);
//处理逻辑
void handleSms(WarningSmsHandlerRequest request, WarningSmsHandlerResult result);
}
复制代码
一个具体请求处理器实现-审核环节短信处理器
/**
* 审核环节短信发送逻辑
*/
public class WarningAuditSmsHandler implements SmsHandler {
@Override
public boolean support(WarningSmsHandlerRequest request) {
return request.getNextWarningState().equals(WarningStatusEnum.WAIT_AUDIT);
}
@Override
public void handleSms(WarningSmsHandlerRequest request, WarningSmsHandlerResult result) {
//处理审核短信
System.out.println("处理审核短信发送逻辑");
}
}
复制代码
一个具体请求处理器实现-处置环节短信处理器
/**
* 处置环节短信发送逻辑
*/
public class WarningHandleSmsHandler implements SmsHandler {
@Override
public boolean support(WarningSmsHandlerRequest request) {
return request.getNextWarningState().equals(WarningStatusEnum.HANDLE);
}
@Override
public void handleSms(WarningSmsHandlerRequest request, WarningSmsHandlerResult result) {
//处理审核短信
System.out.println("处理处置短信发送逻辑");
}
}
复制代码
处理器写好了,怎么让他们一起串起来了? 一般的写法是每个处理器有一个设置下一个处器的方法(setNext),指定下次执行的处理器。 这种写法在有顺序要求的链路处理中比较常用,在以后修改或新增处理器都需要修改setNext方法。 在本次案例中,每个节点都会调用这个发送短信流程,每个处理器都有一个support方法,每次都会根据当前请求过滤出需要处理的处理器。
构造处理器调用链接口
public interface WarningSmsHandlerInvocation {
WarningSmsHandlerResult invoke(WarningSmsHandlerRequest request);
}
复制代码
构造处理器调用链接口实现
@Component
@Setter
public class WarningSmsHandlerInvocationImpl implements WarningSmsHandlerInvocation {
//通过spring注入所有SmsHandler类型的bean
@Autowired
private List<SmsHandler> smsHandlers;
@Override
public WarningSmsHandlerResult invoke(WarningSmsHandlerRequest request) {
WarningSmsHandlerResult result = new WarningSmsHandlerResult();
//依次调用所有匹配当前请求的处理器
for (SmsHandler smsHandler : smsHandlers) {
if (smsHandler.support(request)) {
smsHandler.handleSms(request, result);
}
}
return result;
}
}
复制代码
使用写好的处理链调用器进行测试
@Component
public class WarningSmsHandlerClient {
@Autowired
private WarningSmsHandlerInvocation invocation;
public void testSmsSend() {
WarningSmsHandlerRequest request = new WarningSmsHandlerRequest();
request.setNextWarningState(WarningStatusEnum.WAIT_AUDIT);
WarningSmsHandlerResult result = invocation.invoke(request);
System.out.println(result);
}
}
复制代码
如果需要新增一个处理器,则只要实现WarningAuditSmsHandler接口就可以了。
总结
通过使用责任链模式,可以降低业务代码的耦合度,提升整体的可扩展性和可维护性。
- 每个具体处理器只要处理自己负责的业务,符合单一职责原则
- 新增,修改,删除,都不会修改调用器的逻辑
- 上一篇: 可视化代理神器,动动手指轻松配置Nginx
- 下一篇: 行为参数化——使用lambda传递代码
猜你喜欢
- 2024-09-26 如何避免重复提交?分布式服务的幂等性设计
- 2024-09-26 聊聊如何实现一个带幂等模板的Kafka消费者
- 2024-09-26 Docker 安装 Kibana(DOCKER 安装UNTUNTU 图形界面 装不上)
- 2024-09-26 「优雅代码」03-optional杜绝空指针异常
- 2024-09-26 Mybatis plus通用字段自动填充的最佳实践总结
- 2024-09-26 不吹牛逼,撸个注解有什么难的(切记不吹牛)
- 2024-09-26 ElasticSearch入门一:入门安装和索引基本操作
- 2024-09-26 如何优雅地记录操作日志?(如何优雅地记录操作日志)
- 2024-09-26 使用Java8改造出来的模板方法真的是yyds
- 2024-09-26 java利用枚举与数据库交互(java利用枚举与数据库交互方式)
你 发表评论:
欢迎- 07-03win7去掉桌面图标小箭头怎么操作 win7桌面快捷方式箭头怎么去除
- 07-03win7声音图标不见了怎么办(windows7声音没了怎么办)
- 07-03男生勿入:Win10/Win7/Win8.1女生图标下载
- 07-03桌面只有回收站图标,给Win7/10系统在桌面添加“计算机”图标
- 07-03经典windows桌面图标手机壁纸(经典windows桌面背景)
- 07-03如何在Win10启用Win7/Win8.1通知区域图标设置?
- 07-03win7声音图标不见了解决步骤(win7旗舰版声音图标不显示)
- 07-03为什么回收站图标没了?win11/win10/win7电脑如何显示回收站图标
- 最近发表
-
- win7去掉桌面图标小箭头怎么操作 win7桌面快捷方式箭头怎么去除
- win7声音图标不见了怎么办(windows7声音没了怎么办)
- 男生勿入:Win10/Win7/Win8.1女生图标下载
- 桌面只有回收站图标,给Win7/10系统在桌面添加“计算机”图标
- 经典windows桌面图标手机壁纸(经典windows桌面背景)
- 如何在Win10启用Win7/Win8.1通知区域图标设置?
- win7声音图标不见了解决步骤(win7旗舰版声音图标不显示)
- 为什么回收站图标没了?win11/win10/win7电脑如何显示回收站图标
- Win7怎么更换本地磁盘图标?(win7桌面改d盘)
- Win7桌面图标消失怎么办?(win7桌面图标全没了怎么办)
- 标签列表
-
- 电脑显示器花屏 (79)
- 403 forbidden (65)
- linux怎么查看系统版本 (54)
- 补码运算 (63)
- 缓存服务器 (61)
- 定时重启 (59)
- plsql developer (73)
- 对话框打开时命令无法执行 (61)
- excel数据透视表 (72)
- oracle认证 (56)
- 网页不能复制 (84)
- photoshop外挂滤镜 (58)
- 网页无法复制粘贴 (55)
- vmware workstation 7 1 3 (78)
- jdk 64位下载 (65)
- phpstudy 2013 (66)
- 卡通形象生成 (55)
- psd模板免费下载 (67)
- shift (58)
- localhost打不开 (58)
- 检测代理服务器设置 (55)
- frequency (66)
- indesign教程 (55)
- 运行命令大全 (61)
- ping exe (64)
本文暂时没有评论,来添加一个吧(●'◡'●)