参考:https://zhuanlan.zhihu.com/p/553917078?utm_id=0
一、责任链模式
责任链模式(Chain of Responsibility Pattern)是将链中每一个节点看作是一个对象,每个节点处理的请求均不同,且内部自动维护一个下一节点对象。当一个请求从链式的首端发出时,会沿着链的路径依次传递给每一个节点对象,直至有对象处理这个请求为止。属于行为型模式。
二、责任链模式的优缺点
1、优点
减少大量ifelse;
逻辑清晰明了,添加删除节点、改变节点顺序方便快捷;
请求与处理解耦;
请求处理者只需关注自己感兴趣的请求,对于不感兴趣的请求,直接转发给下一级节点对象;
易于扩展新的请求处理类,符合开闭原则;
2、缺点
责任链太长或处理时间过长,会影响整体性能。
如果需要判断的东西较多,容易造成类保证;
如果每个判断逻辑较简单,可能会造成一个类只做一个小小的数值判断,哈哈;
如果节点对象存在循环链接,可能会造成死循环;
三、实践
传统方法
@Data
public class Programmer {
// 姓名
private String name;
// 项目
private String project;
// 模块
private String module;
// 进度
private double schedule;
// 计划完成时间
private Date completePlanTime;
// 详细信息
private String info;
}
public class Check {
public boolean programmerCheck(Programmer programmer){
if(!"公众号".equals(programmer.getProject())){
return false;
}
if(!"哪吒编程".equals(programmer.getName())){
return false;
}
if(!programmer.getInfo().equals("公众号哪吒编程,定期分享Java干货,还有不定期的送书活动,包邮到你家,哈哈")){
return false;
}
return true;
}
}
通过责任链模式重构代码
1、链路抽象类定义
这部分是责任链模式的核心代码,重点在于通过next获取下一个节点。
定义一个抽象方法doHandler供子类去实现,实现不同的业务逻辑
public abstract class Handler<T> {
protected Handler next;
private void next(Handler next) {
this.next = next;
}
public abstract boolean doHandler(Programmer programmer);
public static class Builder<T> {
private Handler<T> head;
private Handler<T> tail;
public Builder<T> addHandler(Handler handler) {
if (this.head == null) {
this.head = this.tail = handler;
return this;
}
this.tail.next(handler);
this.tail = handler;
return this;
}
public Handler<T> build() {
return this.head;
}
}
}
(1)项目名称检验
/**
* 校验项目名称
*/
public class ProjectHandler extends Handler {
@Override
public boolean doHandler(Programmer programmer) {
if(!"公众号".equals(programmer.getProject())){
return false;
}
if(null == next){
return true;
}
return next.doHandler(programmer);
}
}
校验名字
/**
* 校验名字
*/
public class NameHandler extends Handler {
@Override
public boolean doHandler(Programmer programmer) {
if(!"哪吒编程".equals(programmer.getName())){
return false;
}
if(null == next){
return true;
}
return next.doHandler(programmer);
}
}
校验活动细节
/**
* 校验活动细节
*/
public class InfoHandler extends Handler {
@Override
public boolean doHandler(Programmer programmer) {
if(!programmer.getInfo().contains("扫描文末二维码,关注公众号哪吒编程,定期分享Java干货,还有不定期的送书活动,包邮到你家")){
return false;
}
if(null == next){
return true;
}
return next.doHandler(programmer);
}
}
测试
核心代码流程:
调用流程:
(1)new Hadnler.Builder() 构建Builder类对象
(2)addHandler(new ProjectHandler()) 此时this.head为空。this.head 和this.tail的地址指向 new ProjectHandler()的地址
(3)addHandler(new NameHandler()) 此时的this.head不为空,走下面,this.tail.next指向NameHandler。因为(2)的this.head = this.tail,此时的是引用传递,传递的是内存地址。所以内存地址的next为NameHandler,所以this.head的next为NamHandler。然后this.tail的地址指向NameHandler的地址
(4)addHandler(new InfoHandler())此时this.tail指向NameHandler。他的next指向InfoHandler,所以NameHandler的next指向InfoHandler。然后将他指向InfoHandler
(5)build 获得this.head,然后doHandler()处理,里面的next.doHandler调用NameHandler处理,依次.....