【设计模式】责任是责任,链是链,责任链模式是什么?

1,448 阅读7分钟

这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战

一、什么是责任链模式
1.先看看百度百科是怎么解释的

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

我们可以理解到,责任链就是多个对象一起共同对一个请求进行处理,这里还提到的,直到链上的某一个对象决定处理此请求。如果只是有一个对象对请求进行处理的话,那为什么要花费这么大的力气去组成这一条责任链呢?这不是多此一举吗?

2.我对责任链的看法

首先,责任链的这个设计模式,肯定是将一个请求分散给多个对象处理,为了更加的直观方便,于是将处理对象串成一条链条,让它们一直调用下家来进行处理这个请求。 其次,责任链并不是只有一个对象决定对请求进行处理,而是全部对象共同对这个请求进行处理,只是分别在不同的维度上而已。

简单地画个图作为对责任链的描述 在这里插入图片描述

3.使用责任链的优缺点
优点
  1. 让每个类更加地专注自己的责任。
  2. 使编码过程更加的清晰。
  3. 降低耦合度。降低了代码的复杂度
  4. 新增或修改更加方便
缺点
  1. 处理存在延迟
  2. 不能保证请求一定被处理
  3. 责任链较长会影响系统性能
  4. 进行代码调试时不方便
原则

“+”代表遵守,“-”代表不遵守或者不相关

原则开放封闭单一职责迪米特里氏替换依赖倒置接口隔离合成复用
++--+--
二、增强型责任链(过滤器)

因为感觉跟增强型代理特别像,就比较大胆地将名字取成了增强型责任链,它也可以叫过滤器。

1.特点
  1. 最终处理对象不变
  2. 使用习惯不变
  3. 业务无关性
  4. 附加新功能
  5. 请求一定会被处理

总的来说,增强型责任链的处理对象仍然是只有一个,很符合百度百科的解释,就是整一条责任链中,只有最后一个对象才会对请求进行处理,其他的都是在作一些记录,或者是上锁,都是一切无关业务的操作。增强型责任链更加侧重的点是无关业务逻辑的操作。

2.常见的例子
  1. tomcat中的Filter接口,在请求的时候采用了这种增强型责任链,最终处理请求的对象没有改变,它是一层一层地将request和response传递给servlet对象处理的。
  2. struts2中也存在过滤器,具体用来干嘛的,我也想不起来了,好像是用来校验的。
三、拦截器责任链
1.特点
  1. 最终处理对象不变
  2. 使用习惯不变
  3. 改变业务逻辑
  4. 请求不一定被处理

总的来说,拦截器责任链会影响到业务的逻辑,一旦其中的一个对象验证时不符合条件,就会中断整个请求,就像是一系列的if包裹在一起。拦截器责任链更加侧重的点是业务逻辑。

2.常见的例子
  1. HandlerInterceptorAdapter类
  2. 同样是struts2里面也有拦截器,可以用作拦截用户无登陆进入网站。
  3. spring中也有拦截器
四、过程型责任链(pipeline责任链)
1.特点
  1. 处理对象不单一
  2. 责任链对象顺序有要求
  3. 使用更加方便
  4. 业务无关性
  5. 请求一定会被处理

总的来说,过程型责任链就是将一个请求分给多个对象进行处理,处理的顺序有些会存在严格要求,当全部对象都进行了处理之后就会返回。有点像链接型代理,对多个方法进行了封装,但是过程型责任链对处理的顺序有要求。过程型责任链更加侧重的点是处理的过程。

2.常见的例子
  1. Jenkins打包工具,它就是将源代码处理成字节码,再打包成wai包,然后发布。
五、总结

增强型责任链更加侧重的点是无关业务逻辑的操作。 拦截器责任链更加侧重的点是业务逻辑。 过程型责任链更加侧重的点是处理的过程。 这三个责任链分别从三个维度出发,形成了各有特色的责任链。 不排除以后会出现更多的责任链,但是它们的本质都是从不同维度对一个请求进行处理,它们的形式都是一个链条。

六、责任链简单的实现方式

这是仿照tomcat里的过滤器责任链来实现的,想要实现其他的责任链,做出一些修改即可。

  1. 先创建一个Filter接口,作为责任链中存放对象的原型
package responsibilitychain;
​
/**
 * @author xxj
 * 过滤器
 */
public interface Filter {
    /**
     * 责任链中最终执行的方法
     * @param object 传递的需要处理的对象
     * @return 改成boolean的话就是拦截器了,
     */
    void doFilter(Object object);
}
  1. 创建一个FilterChain类,作为责任链管理器
package responsibilitychain;
​
import java.util.ArrayList;
import java.util.List;
​
/**
 * @author xxj
 * 责任链管理器
 */
public class FilterChain implements Filter {
    List<Filter> list =new ArrayList<>();
    public void addFilter(Filter filter){
        list.add(filter);
    }
    @Override
    public void doFilter(Object object) {
        list.forEach(f -> f.doFilter(object));
    }
}
​
  1. 使用责任链 每个责任链对象都需要单独创建一个类,这个类需要实现Filter接口
package responsibilitychain;
​
/**
 * @author xxj
 * 测试责任链
 * 对一个String对象进行修改
 */
public class test {
    public static void main(String[] args){
        //创建责任链管理器
        FilterChain filterChain=new FilterChain();
        //添加责任链
        filterChain.addFilter(new FirstFilter());
        filterChain.addFilter(new SecondFilter());
        filterChain.addFilter(new LastFilter());
        //调用责任链
        String string="   aaa    ";
        filterChain.doFilter(string);
    }
    static class FirstFilter implements Filter{
        @Override
        public void doFilter(Object object) {
            //强转成String
            String string=(String)object;
            //输出String的长度
            System.out.println(string.length());
​
        }
    }
    static class SecondFilter implements Filter{
        @Override
        public void doFilter(Object object) {
            //强转成String
            String string=(String)object;
            //去掉空格
            string=string.trim();
            //再输出长度
            System.out.println(string.length());
        }
    }
    static class LastFilter implements Filter{
        @Override
        public void doFilter(Object object) {
            //强转成String
            String string=(String)object;
            //输出string
            System.out.println(string);
​
        }
    }
}
  1. 输出的结果
10
3
   aaa    
​

责任链模式除了这种实现方式之外,还有一种实现方式,定义跟过滤器一样的接口,名称的话叫chain也行,然后定义一些行为,这里的行为是需要跟你最终想要使用的对象一样,例如一个数据对象LogData有get和set方法,那这个接口就要有get和set方法,然后实现一系列的chain类,这些chain类内部需要声明一个chain的成员变量,这个成员用于指向下一个chain对象,还有get或set方法都需要去调用这个chain对象的get或set方法,接下来就是要组成我们的责任链了,把一个个chain实现类的对象组成一条链子,在创建对象时就要传递下一个责任链节点的对象进入,直到最终想要使用的对象。

——————————————————————————————

你知道的越多,不知道的就越多。

如果本文章内容有问题,请直接评论或者私信我。如果觉得我写得还不错的话,点个赞也是对我的支持哦

未经允许,不得转载!