本篇文章讲解责任链设计模式
责任链模式 顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
需求
在公司流程处理业务中,有不同的处理流程节点,在不同的节点需要发送不同的短信,用来通知下一个节点的处置人。
1发起->2审核->3处置->4结果审核->完成,每个环节还可以有退回到上一个节点的功能,而且不同的地区还可能有其他的流程节点。一开始产品只提出审核和处置两个节点需要发送短信,所有一开始的代码是这样写的。
public class WarningSmsHandler {public void sendSms() {//处理发送短信逻辑if(是否是审核完成) {//查询处置人,设置短信内容,发送短信} else if(是否是处置完成) {//查询结果审核人,设置短信内容,发送短信}}}
随着时间推移,产品又提出需要在发起环节发送短信,通知审核人。这个时候可以选择修改原来的WarningSmsHandler类,这样现在实现起来是比较快的,但是这样也会给以后带来一些问题:
随着越来越多节点的短信发送需求,后面会不断的在这个类加代码,违反了单一职责原则。
以后加一个节点的短信,删除一个节点的短信,都需要改WarningSmsHandler类的代码,违背开闭原则。
所以必须思考下如何选择一个周全的方案,避免这些问题。
回到需求,短信发送是上一个节点发送给下一个节点,一般只发送给下一个节点的人。这里想到使用责任链模式,将各个节点发送短信的逻辑进行拆分,单一职责。
根据责任链模式实现该需求
1、定义统一请求类
public class WarningSmsHandlerRequest{//通报idprivate Long warningId;//下一个通报状态private WarningStateEnum nextWarningState;//下一个通报处置人类型private WarningHandleUnitEnum warningHandleUnitEnum;//附加参数private List<String> attachmentParam;//短信模版id 有些短信厂商需要模版private String templateId;}
2、定义统一处理结果类
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 {public boolean support(WarningSmsHandlerRequest request) {return request.getNextWarningState().equals(WarningStatusEnum.WAIT_AUDIT);}public void handleSms(WarningSmsHandlerRequest request, WarningSmsHandlerResult result) {//处理审核短信System.out.println("处理审核短信发送逻辑");}}
一个具体请求处理器实现-处置环节短信处理器
/*** 处置环节短信发送逻辑*/public class WarningHandleSmsHandler implements SmsHandler {public boolean support(WarningSmsHandlerRequest request) {return request.getNextWarningState().equals(WarningStatusEnum.HANDLE);}public void handleSms(WarningSmsHandlerRequest request, WarningSmsHandlerResult result) {//处理审核短信System.out.println("处理处置短信发送逻辑");}}
处理器写好了,怎么让他们一起串起来了?
一般的写法是每个处理器有一个设置下一个处器的方法(setNext),指定下次执行的处理器。
这种写法在有顺序要求的链路处理中比较常用,在以后修改或新增处理器都需要修改setNext方法。
在本次案例中,每个节点都会调用这个发送短信流程,每个处理器都有一个support方法,每次都会根据当前请求过滤出需要处理的处理器。
构造处理器调用链接口
public interface WarningSmsHandlerInvocation {WarningSmsHandlerResult invoke(WarningSmsHandlerRequest request);}
构造处理器调用链接口实现
public class WarningSmsHandlerInvocationImpl implements WarningSmsHandlerInvocation {//通过spring注入所有SmsHandler类型的beanprivate List<SmsHandler> smsHandlers;public WarningSmsHandlerResult invoke(WarningSmsHandlerRequest request) {WarningSmsHandlerResult result = new WarningSmsHandlerResult();//依次调用所有匹配当前请求的处理器for (SmsHandler smsHandler : smsHandlers) {if (smsHandler.support(request)) {smsHandler.handleSms(request, result);}}return result;}}
使用写好的处理链调用器进行测试
public class WarningSmsHandlerClient {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接口就可以了。
总结
通过使用责任链模式,可以降低业务代码的耦合度,提升整体的可扩展性和可维护性。
* 每个具体处理器只要处理自己负责的业务,符合单一职责原则
* 新增,修改,删除,都不会修改调用器的逻辑。
以上全部内容,如果有更好的设计欢迎交流探讨。
原文作者:服务端技术栈;如有侵权,请联系管理员删除。