[Design Pattern] Easy-to-understand Chain of Responsibility Pattern

introduce

In the process of automobile production, it is necessary to carry out strict quality inspection on various parts of the car, such as engine, gearbox, body, etc., and filter unqualified parts.

Filter inspection of auto parts

In general, we can do this by writing:

public class Client {
    public static void main(String[] args) {
        Client client = new Client();

        Request req = new Request();
        req.setReqMsg("检查发动机,变速箱,车身有没有问题");
        if (req.getReqMsg().contains("车身")) {
            client.doCheckCarbody();
        }
        if (req.getReqMsg().contains("发动机")) {
            client.doCheckEngine();
        }
        if (req.getReqMsg().contains("变速箱")) {
            client.doCheckGearbox();
        }
        if (req.getReqMsg().contains("xxx")) {
            // do something
        }
    }

    public void doCheckEngine () {
        System.out.println("------检查了发动机------");
    }

    public void doCheckCarbody () {
        System.out.println("------检查了车身-------");
    }

    public void doCheckGearbox () {
        System.out.println("------检查了变速箱-----");
    }
}

class Request {
    private String reqMsg;

    public String getReqMsg() {
        return reqMsg;
    }

    public void setReqMsg(String reqMsg) {
        this.reqMsg = reqMsg;
    }
}
复制代码

but, see

if (req.getReqMsg().contains("xxx")) {
    // do something
}
复制代码

Is this? This means more things to check and more ifstatements (so familiar code, haha)

How to get rid of bloated if, elegantly perform auto parts inspection?

For the above code, if one day a part is exempted from inspection, it does not need to be inspected, and a certain ifbranch has to be removed. At this time, you can't wait to refactor all the code. . .

Object-oriented has a word called encapsulation change , which means that which part needs to be changed, we can encapsulate which part , we can encapsulate the part that deals with car parts.

code show as below:

public class Client {
    public static void main(String[] args) {
        Request req = new Request();
        req.setReqMsg("检查发动机,变速箱,车身有没有问题");

        List<Filter> filters = new ArrayList<>();
        filters.add(new CarbodyFilter());
        filters.add(new GearboxFilter());
        filters.add(new EngineFilter());

        for (Filter f : filters) {
            f.doFilter(req);
        }
    }
}

class Request {
    private String reqMsg;

    public String getReqMsg() {
        return reqMsg;
    }

    public void setReqMsg(String reqMsg) {
        this.reqMsg = reqMsg;
    }
}

interface Filter {
    boolean doFilter(Request request);
}

class EngineFilter implements Filter {
    @Override
    public boolean doFilter(Request request) {
        if (request.getReqMsg().contains("发动机")) {
            System.out.println("------检查了发动机------");
        }
        return true;
    }
}

class GearboxFilter implements Filter {
    @Override
    public boolean doFilter(Request request) {
        if (request.getReqMsg().contains("变速箱")) {
            System.out.println("------检查了变速箱------");
        }
        return true;
    }
}

class CarbodyFilter implements Filter {
    @Override
    public boolean doFilter(Request request) {
        if (request.getReqMsg().contains("车身")) {
            System.out.println("------检查了车身------");
        }
        return true;
    }
}
复制代码

In this way, if you want to check which part, you only need to ask

List<Filter> filters = new ArrayList<>();
复制代码

filtersJust add Filterit in. Is this code a little bit more interesting?

There is no most elegant, only more elegant

The code of the previous version still needs to Clientbe List<Filter>added in the inside to be executed, Filterwhich is almost meaningless.

Let's take a look at the scenario described above:

Does each perform their Filterown duties , as long as Filterthey are linked together and let them execute it internally!

Then let's write a FilterChainto string them together:

class FilterChain implements Filter {
    List<Filter> filters = new ArrayList<>();

    //比较骚的写法,这样可以链式调用
    public FilterChain add(Filter filter) {
        filters.add(filter);
        return this;
    }
    //一般写法
//    public void add(Filter filter) {
//        filters.add(filter);
//    }

    @Override
    public boolean doFilter(Request request) {
        for (Filter f : filters) {
            //任何一环检查出了问题,均不往下检查
            if (!f.doFilter(request)) {
                return false;
            }
        }
        return true;
    }
}
复制代码

Here FilterChainis the addmethod in the text, first look at the general writing method:

public void add(Filter filter) {
    filters.add(filter);
}
复制代码

Then the call has to be done like this:

FilterChain chain = new FilterChain();
chain.add(new EngineFilter());
chain.add(new GearboxFilter());
chain.add(new CarbodyFilter());
chain.doFilter(req);
复制代码

There is a more saucy way of writing:

public FilterChain add(Filter filter) {
    filters.add(filter);
    return this;
}
复制代码

transfer:

FilterChain chain = new FilterChain();
chain.add(new EngineFilter())
        .add(new GearboxFilter())
        .add(new CarbodyFilter())
        .doFilter(req);
复制代码

Huh? I have seen this way of writing in the xx source code! It feels like it has improved a few grades in an instant.

The above FilterChainversion is actually the Chain of Responsibility model ! ! !

似曾相识的FilterChain

没错,如果你开发过Java Web程序,你一定见过这个东西。

比如 ServletFilterStrutsInterceptorSpring MVCHandlerInterceptor 。它们本质上都是过滤器或者叫拦截器。

JavaEE Filter

我用刚才的场景

模拟了一下FilterFilterChain

public class Client {
    public static void main(String[] args) {
        Request request = new Request();
        request.reqMsg = "检查发动机,变速箱,车身有没有问题";
        Response response = new Response();
        response.respMsg = "-------response:";

        FilterChain chain = new FilterChain();
        chain.add(new EngineFilter()).add(new GearboxFilter()).add(new CarbodyFilter());
        chain.doFilter(request, response);

        System.out.println(response.respMsg);
    }
}

class Request {
    String reqMsg;
}

class Response {
    String respMsg;
}

interface Filter {
    void doFilter(Request request, Response response, FilterChain chain);
}

class EngineFilter implements Filter {
    public void doFilter(Request request, Response response, FilterChain chain) {
        //先处理request请求
        if (request.reqMsg.contains("发动机")) {
            System.out.println("------EngineFilter 检查了发动机------");
        }
        //通过链条传递处理下一个request
        chain.doFilter(request, response);
        //处理response
        response.respMsg += "---执行了EngineFilter过滤器---";
    }
}

class GearboxFilter implements Filter {
    public void doFilter(Request request, Response response, FilterChain chain) {
        if (request.reqMsg.contains("变速箱")) {
            System.out.println("------GearboxFilter 检查了变速箱------");
        }
        //通过链条传递处理下一个request
        chain.doFilter(request, response);
        //处理response
        response.respMsg += "---执行了GearboxFilter过滤器---";
    }
}

class CarbodyFilter implements Filter {
    public void doFilter(Request request, Response response, FilterChain chain) {
        if (request.reqMsg.contains("车身")) {
            System.out.println("------CarbodyFilter 检查了车身------");
        }
        //通过链条传递处理下一个request
        chain.doFilter(request, response);
        //处理response
        response.respMsg += "---执行了CarbodyFilter过滤器---";
    }
}

class FilterChain {
    List<Filter> filters = new ArrayList<>();
    int filterIndex = 0;

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

    public void doFilter(Request request, Response response) {
        //如果request链条执行完了,就不往下传递了
        if (filterIndex == filters.size()) {
            return;
        }
        Filter f = filters.get(filterIndex);
        filterIndex++;
        f.doFilter(request, response, this);
    }
}
复制代码

捋一捋:

FilterChain 里面定义了一个 filterIndex 来控制链条顺序执行,并且在每个filter的doFilter里

  1. 先处理request
  2. 调用chain.doFilter(request, response)传递链条
  3. 处理response

看下执行结果:

这些框架的过滤器、拦截器使用的也是 责任链模式

小结

  • 责任链模式 (Chain of Responsibility)是一种 处理请求 的模式,它让多个处理器都有机会处理该请求,直到其中某个处理成功为止。责任链模式把多个处理器串成链,然后让请求在链上传递。
  • 责任链模式在添加新的处理类或者排列处理请求的顺序上非常容易。
  • 拦截、预处理请求等场景下经常会用到责任链模式。

暗示自己:好好学习设计模式,咱也能写出优秀的代码!!!

以上。

点个赞再走吧~

我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿

Guess you like

Origin juejin.im/post/7120039388620259359