构造模式+责任链模式实现链式调用(可以用于参数校验等)

发布时间 2023-07-06 23:24:19作者: spiderMan1-1

参考: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处理,依次.....