ITPub博客

首页 > 数据库 > 数据库开发技术 > 学会了这个设计模式,再也不是只会写if/else了

学会了这个设计模式,再也不是只会写if/else了

原创 数据库开发技术 作者:服务端技术栈 时间:2021-04-29 20:16:26 0 删除 编辑

本篇文章讲解责任链设计模式


责任链模式 顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。


需求

在公司流程处理业务中,有不同的处理流程节点,在不同的节点需要发送不同的短信,用来通知下一个节点的处置人。

1发起->2审核->3处置->4结果审核->完成,每个环节还可以有退回到上一个节点的功能,而且不同的地区还可能有其他的流程节点。一开始产品只提出审核和处置两个节点需要发送短信,所有一开始的代码是这样写的。

public class WarningSmsHandler {

public void sendSms() { //处理发送短信逻辑 if(是否是审核完成) { //查询处置人,设置短信内容,发送短信 } else if(是否是处置完成) { //查询结果审核人,设置短信内容,发送短信 } }}


随着时间推移,产品又提出需要在发起环节发送短信,通知审核人。这个时候可以选择修改原来的WarningSmsHandler类,这样现在实现起来是比较快的,但是这样也会给以后带来一些问题:

  • 随着越来越多节点的短信发送需求,后面会不断的在这个类加代码,违反了单一职责原则。

  • 以后加一个节点的短信,删除一个节点的短信,都需要改WarningSmsHandler类的代码,违背开闭原则。


所以必须思考下如何选择一个周全的方案,避免这些问题。

回到需求,短信发送是上一个节点发送给下一个节点,一般只发送给下一个节点的人。这里想到使用责任链模式,将各个节点发送短信的逻辑进行拆分,单一职责。

根据责任链模式实现该需求


1、定义统一请求类

@Datapublic class WarningSmsHandlerRequest{

//通报id private Long warningId; //下一个通报状态 private WarningStateEnum nextWarningState; //下一个通报处置人类型 private WarningHandleUnitEnum warningHandleUnitEnum; //附加参数 private List<String> attachmentParam; //短信模版id 有些短信厂商需要模版 private String templateId;}


2、定义统一处理结果类

@Datapublic 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@Setterpublic 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; }}

使用写好的处理链调用器进行测试

@Componentpublic 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接口就可以了。


 总结

通过使用责任链模式,可以降低业务代码的耦合度,提升整体的可扩展性和可维护性。

* 每个具体处理器只要处理自己负责的业务,符合单一职责原则

* 新增,修改,删除,都不会修改调用器的逻辑。


以上全部内容,如果有更好的设计欢迎交流探讨。

原文作者:服务端技术栈;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2019-03-08

  • 博文量
    97
  • 访问量
    41441