《一天一模式》— 责任链模式

原创
2020/05/23 00:30
阅读数 184

一、责任链模式的概念

责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。

二、什么时候使用责任链模式

根据概念理解,责任链模式是一种可以处理一次请求流的一种模式,类似业务工作流程,而且责任链可以动态的调整流程中的各个环节。

也就是说,如果业务里有这种需要逐级处理的业务,可是尝试使用责任链模式。

我在项目中,一般需要逐级做业务判断的时候会使用工作流模式,例如:

http请求拦截器,先判断HttpHeader的协议是否正确,在判断登录信息是否正确,在判断请求内容是否正确等,这几步判断就可以用责任链模式实现;

从代码结构角度,可以解决嵌套if的问题,例如:

if (验证协议) {
    ....
    if (验证鉴权) {
        ....
        if (验证数据) {
            ....
        }
    }
}

可以避免这种嵌套if结构,提升代码的可读性。下面来试着用Java代码实现责任链模式。

三、怎么使用责任链模式

3.1 实现方式

就以请求拦截器为例,模拟做一个责任链模式,一共三步验证:

  • 验证协议是否正确;
  • 验证登录信息是否正确;
  • 验证请求数据是否正确;

下面是类图和代码:

// 责任链模式的抽象类
public abstract class Validator {

    // 设置责任链的下一个环节
    private Validator next;

    public Validator setNext(Validator next) {
        this.next = next;
        // 返回下一个环节,做到链式设置
        return next;
    }

    // 开始责任链的处理
    public final void handler(List<String> context) {
        if (!resolve(context)) { // 判断处理结果是否失败,如果失败则不向下进行
            fail(context);
        } else if (next != null) { // 如果本环节处理成功,判断是否还有下一环节,如果就,就执行下一个环节的handler
            next.handler(context);
        } else { // 如果处理成功,切没有下一个环节了,责任链结束
            success(context);
        }
    }

    // 具体处理业务的方法,定义一个抽象方法等待被子类实现(类似模板方法模式)
    protected abstract boolean resolve(List<String> context);

    // 成功通过的处理
    protected void success(List<String> context) {
        System.out.println("验证通过。");
    }

    // 未成功通过的处理
    protected void fail(List<String> context) {
        System.out.println("验证失败。");
    }

}

// 验证鉴权的处理类
public class AuthValidator extends Validator {

    public boolean resolve(List<String> context) {
        return context.get(1).equals("admin");
    }
}

// 验证协议的处理类
public class ProtocolValidator extends Validator {

    public boolean resolve(List<String> context) {
        return context.get(0).equals("http");
    }
}

// 验证数据的处理类
public class DataSecurityValidator extends Validator {

    public boolean resolve(List<String> context) {
        return context.get(2).equals("hello");
    }
}

上面是责任链模式的类图和代码,从代码上看,抽象类定义了责任链的创建方法,和循环调用方法,但具体的处理,需要有子类的实现(类似模板方法),然后在成功或者失败的时候,进行相关处理,责任链模式的使用方式如下:

public class Client {

    public static void main(String[] args) {

        // 因为是测试,所以在此处配置了责任链的关系,正常情况下,Client是不需要知道责任链的配置关系的
        Validator protocolValidator = new ProtocolValidator();
        Validator authValidator = new AuthValidator();
        Validator dataSecurityValidator = new DataSecurityValidator();
        protocolValidator.setNext(authValidator).setNext(dataSecurityValidator);
        // 处理,模拟验证通过
        List<String> params1 = new ArrayList<String>();
        params1.add("http");
        params1.add("admin");
        params1.add("hello");
        protocolValidator.handler(params1);
        // 处理,模拟验证失败
        List<String> params2 = new ArrayList<String>();
        params2.add("http");
        params2.add("ss");
        params2.add("hello");
        protocolValidator.handler(params2);
    }

}

先将几个环节通过setNext建立起关联,然后从某个节点(通常是第一个节点)开始调用handler,进行业务的处理。

以上就是责任链模式的Java代码实现。

3.2 责任链模式的好处

责任链模式的好处如下:

  • 可读性高:将嵌套判断的代码块用面向对象的方式去优化,通过良好的命名起到语义化的效果;
  • 灵活性强:可以随意通过setNext配置各个判断环节的前后关系,而不需要修改代码,嵌套if是做不到的;
  • 扩展性强:如后续有需求变更,可以快读的加入新的责任链环节,而无需修改原有代码,符合开闭原则;

四、总结

责任链模式,面相的业务场景相对比较单一,比较好确定在什么业务场景下使用。但是实现的代码比起其他的设计模式,稍微复杂了一点,但也比较好理解。

还有就是,责任链模式的一个隐藏的优点是,它弱化了调用者(Client)和处理者(Validator)之前的关联,调用者其实无需知道责任链的每个环节的关系,只是去调用责任链的hanlder方法即可,这种解除耦合的优点很重要。

以上就是我对责任链模式的一些理解,有不足之处请大家指出,谢谢。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部