行为型设计模式之责任链模式(Chain Of Responsibility)

设计模式之责任链模式


今天我们来学一种开发中经常会遇到的一种模式,比如web开发中的Filter过滤器、Interceptor拦截器等,这些用的就是 责任链模式

责任链模式算是23中设计模式中常见的模式之一了,下面讲一下我对这个设计模式的一些理解:
先来看看我们不使用责任链模式处理一段字符串的代码:

/**
 * 不使用责任链模式的处理逻辑
 */
public class ChainOfResponsibility_01 {
    public static void main(String[] args) {
        String string = "HELLO";
        //第一步添加下划线
        string = doSomething1(string);
        //第二步添加world
        string = doSomething2(string);
        //第三步转小写
        string = doSomething3(string);

        System.out.println(string);
    }

    private static String doSomething1(String s){
        return s+"_";
    }

    private static String doSomething2(String s){
        return s+"world";
    }

    private static String doSomething3(String s){
        return s.toLowerCase();
    }
}

按照我们日常的开发,对数据的不同处理方式可能会拆分成几个小的方法对其进行处理,每个方法里面负责独立的逻辑。这样每个步骤有变化,只需要修改对应的方法内容即可。
但是没新增加一个处理逻辑,都要显示调用,那有没有一种方式可以简化这种调用呢。
我们来看看下面这段代码:

public class ChainOfResponsibility_02 {
    public static void main(String[] args) {
        String string = "HELLO";
        ChainFilter chainFilter = new ChainFilter();
        chainFilter.add(new ConcatDownLineFilter());
        chainFilter.add(new ConcatWorldFilter());
        chainFilter.add(new ConvertLowerCaseFilter());
        String s = chainFilter.doFilter(string);
        System.out.println(s);
    }

    interface Filter{
        abstract String doFilter(String s);
    }

    static class ConcatDownLineFilter implements Filter{
        @Override
        public String doFilter(String s) {
            return s+"_";
        }
    }

    static class ConcatWorldFilter implements Filter{
        @Override
        public String doFilter(String s) {
            return s+"world";
        }
    }

    static class ConvertLowerCaseFilter implements Filter{
        @Override
        public String doFilter(String s) {
            return s.toLowerCase();
        }
    }

    static class ChainFilter{
        List<Filter> filters = new ArrayList<>();

        public void add(Filter filter){
            this.filters.add(filter);
        }

        public String doFilter(String string){
            for (Filter filter : filters) {
                string = filter.doFilter(string);
            }
            return string;
        }
    }
}

从以上代码可以看到,这里使用了初步的责任链模式,ChainFilter中保存了所有的filter,当调用ChainFilter的doFilter时,会遍历保存的所有filter,依次进行逻辑处理,最终可以得到我们想要的结果,而main中只需要按照顺序添加Filter即可。

如果这个时候存在两个ChainFilter的时候,我想传入的参数都需要经过这两个ChainFilter,那这个时候怎么办呢:
一种是等第一个ChainFilter处理完成后,再调用第二个ChainFilter进行处理;
另一种就是讲两个ChainFilter合并成一个ChainFilter,然后调用一次doFilter即可。
第一种方式简单,这里我们演示第二种方式,看代码:

public class ChainOfResponsibility_03 {
    public static void main(String[] args) {
        String string = "HELLO";
        //第一个ChainFilter
        ChainFilter chainFilter = new ChainFilter()
                        .add(new ConcatDownLineFilter())
                        .add(new ConcatWorldFilter());
        //将第二个ChainFilter添加到第一个
        chainFilter.add(new ChainFilter().add(new ConvertLowerCaseFilter()));
        //执行
        String s = chainFilter.doFilter(string);
        System.out.println(s);
    }

    interface Filter{
        abstract String doFilter(String s);
    }

    static class ConcatDownLineFilter implements Filter{
        @Override
        public String doFilter(String s) {
            return s+"_";
        }
    }

    static class ConcatWorldFilter implements Filter{
        @Override
        public String doFilter(String s) {
            return s+"world";
        }
    }

    static class ConvertLowerCaseFilter implements Filter{
        @Override
        public String doFilter(String s) {
            return s.toLowerCase();
        }
    }

    //让ChainFilter也实现Filter,这样其中的属性filters就可以将所有实现了Filter的都保存,
    //包括其余的ChainFilter
    static class ChainFilter implements Filter{
        List<Filter> filters = new ArrayList<>();

        //这里返回ChainFilter,采用了链式编程的方式,操作更方便
        public ChainFilter add(Filter filter){
            this.filters.add(filter);
            return this;
        }

        @Override
        public String doFilter(String string){
            for (Filter filter : filters) {
                string = filter.doFilter(string);
            }
            return string;
        }
    }
}

再继续,如果有要求:当处理到某一个filter时,如果符合条件,要求可以中断调用,只返回当前已经处理的结果,不再往后执行:

public class ChainOfResponsibility_04 {
    public static void main(String[] args) {
        String string = "HELLO";
        //第一个ChainFilter
        ChainFilter chainFilter = new ChainFilter()
                        .add(new ConcatDownLineFilter())
                        .add(new ConcatWorldFilter());
        //将第二个ChainFilter添加到第一个
        chainFilter.add(new ChainFilter().add(new ConvertLowerCaseFilter()));
        //执行
        chainFilter.doFilter(string);
    }

    interface Filter{
        abstract boolean doFilter(String s);
    }

    static class ConcatDownLineFilter implements Filter{
        @Override
        public boolean doFilter(String s) {
            if(null==s || "".equals(s)){
                return false;
            }
            if(s.contains("_")){
                return false;
            }
            System.out.println(s+"_");
            return true;
        }
    }

    static class ConcatWorldFilter implements Filter{
        @Override
        public boolean doFilter(String s) {
            if(null==s || "".equals(s)){
                return false;
            }
            if(s.startsWith("H")){
                return false;
            }
            System.out.println(s+" world");
            return true;
        }
    }

    static class ConvertLowerCaseFilter implements Filter{
        @Override
        public boolean doFilter(String s) {
            if(null==s || "".equals(s)){
                return false;
            }
            System.out.println(s.toLowerCase());
            return true;
        }
    }

    //让ChainFilter也实现Filter,这样其中的属性filters就可以将所有实现了Filter的都保存,
    //包括其余的ChainFilter
    static class ChainFilter implements Filter{
        List<Filter> filters = new ArrayList<>();

        //这里返回ChainFilter,采用了链式编程的方式,操作更方便
        public ChainFilter add(Filter filter){
            this.filters.add(filter);
            return this;
        }

        @Override
        public boolean doFilter(String string){
            for (Filter filter : filters) {
                boolean b = filter.doFilter(string);
                if(!b){
                    return false;
                }
            }
            return true;
        }
    }
}

以上代码,做了部分修改,让doFilter返回boolean值,这样就可以通过返回的值,判断是否需要继续执行其他Filter,而每个Filter里面也可以添加自己的中断逻辑。就类似于web中的拦截器或过滤器,一旦发现权限不足,那么就直接返回,不再往后面进行处理。

现在又有一个要求,模拟处理字符串,要求正序先处理完,然后再逆向处理。(注意:这里的要求并不是当前方法处理完后,立刻处理后续逻辑,而是等所有的Filter都先处理完成后,所有的Filter再从后往前处理):

public class ChainOfResponsibility_05 {
    public static void main(String[] args) {
        String string = "HELLO";
        //第一个ChainFilter
        new ChainFilter().add(new ConcatAFilter())
                .add(new ConcatBFilter())
                .add(new ConcatCFilter())
                .doFilter(string);
    }

    interface Filter{
        abstract void doFilter(String s, ChainFilter f);
    }

    static class ConcatAFilter implements Filter {
        @Override
        public void doFilter(String s, ChainFilter f) {
            System.out.println(s + "_A");
            if(f.hasNext()) {
                f.nextFilter().doFilter(s, f);
            }
            System.out.println(s + "_a");
        }
    }

    static class ConcatBFilter implements Filter {
        @Override
        public void doFilter(String s, ChainFilter f) {
            System.out.println(s + "_B");
            if(f.hasNext()) {
                f.nextFilter().doFilter(s, f);
            }
            System.out.println(s + "_b");
        }
    }

    static class ConcatCFilter implements Filter {
        @Override
        public void doFilter(String s, ChainFilter f) {
            System.out.println(s + "_C");
            if(f.hasNext()) {
                f.nextFilter().doFilter(s, f);
            }
            System.out.println(s + "_c");
        }
    }

    static class ChainFilter{
        List<Filter> filters = new ArrayList<>();
        int index = -1;//记录索引下标
        int count = 0;//filter的总数

        //这里返回ChainFilter,采用了链式编程的方式,操作更方便
        public ChainFilter add(Filter filter){
            this.filters.add(filter);
            count++;
            return this;
        }

        public void doFilter(String s){
            if(hasNext()) {
                this.nextFilter().doFilter(s, this);
            }
        }

        public boolean hasNext(){
            if(index+1>=count){
                return false;
            }
            index++;
            return true;
        }

        public Filter nextFilter(){
            return this.filters.get(index);
        }
    }
}

输出结果:

HELLO_A
HELLO_B
HELLO_C
HELLO_c
HELLO_b
HELLO_a

以上这段代码,做了比较大的改动,首先是Filter的接口中,新增一个ChainFilter,其次ChainFilter不再实现Filter(虽然也可以实现Filter),新增了两个接口,一个是hasNext(),一个nextFilter,其目的是为了判断ChainFilter中索引下标是否超出了filters的总数,如果没有,那么可以继续获取下一个Filter,并调用其doFilter操作,否则执行doFilter后的代码。
以上这段代码类似于Servlet中Filter和FilterChain的定义,我们来看看Servlet中是怎么定义的:

public interface Filter {
    void init(FilterConfig var1) throws ServletException;

    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

    void destroy();
}
public interface FilterChain {
    void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException;
}

以上是Servlet中的责任链的主要两个接口。

还有一种责任链的方式,是真正的逻辑上的链条方式,就是ChainFilter在添加Filter时,记录每个Filter的上一个Filter和下一个Filter,形成真正的链条。但是这种方式类似与集合中的LinkedList,遍历起来耗费性能,没有数组形式的效率高。

最后,是关于责任链的官方定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值