【设计模式】通过java过滤器理解责任链模式

在这里插入图片描述

如图所示,消息在进入数据库之前,会进过多层过滤器,我们可以在过滤器中对消息进行数据处理或者拦截。而这每一个Filter都有自己的责任,串成了一个链条就是责任链。数据按照顺序一层层经过这些过滤器。
直接上代码
简单说一下需求:有一个消息经过filter1,filter2. filter1和filter2都为该消息添加一些自己的字符串。

import java.util.ArrayList;
import java.util.List;

public class FilterMain {
    public static void main(String[] args) {
        Msg msg = new Msg();
        msg.setMsg("hello world");
		// 通过集合存储,将过滤器组合成一条责任链
        List<Filter> filters = new ArrayList<>();
        filters.add(new Filter1());
        filters.add(new Filter2());

        for (Filter f : filters) {
            f.doFilter(msg);
        }
        System.out.println(msg); // hello world--经过filter1--经过filter2
    }
}

class Msg{
    private String msg;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    @Override
    public String toString() {
        return msg;
    }
}

interface Filter{
    void doFilter(Msg m);
}

class Filter1 implements Filter{
    @Override
    public void doFilter(Msg m) {
        m.setMsg(m.getMsg()+"--filter1");
    }
}

class Filter2 implements Filter{
    @Override
    public void doFilter(Msg m) {
        m.setMsg(m.getMsg()+"--filter2");
    }
}

然后我们可以将Main方法中的

       // 通过集合存储,将过滤器组合成一条责任链
        List<Filter> filters = new ArrayList<>();
        filters.add(new Filter1());
        filters.add(new Filter2());

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

抽离出来封装成一个FilterChain具体代码如下

import java.util.ArrayList;
import java.util.List;
//使用FilterChain
public class FilterMain {
    public static void main(String[] args) {
        Msg msg = new Msg();
        msg.setMsg("hello world");
        FilterChain fc = new FilterChain();
        fc.add(new Filter1())
          .add(new Filter2());
        fc.doFilter(msg);
        System.out.println(msg);
    }
}

class Msg{
    private String msg;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    @Override
    public String toString() {
        return msg;
    }
}

interface Filter{
    void doFilter(Msg m);
}

class Filter1 implements Filter{
    @Override
    public void doFilter(Msg m) {
        m.setMsg(m.getMsg()+"--filter1");
    }
}

class Filter2 implements Filter{
    @Override
    public void doFilter(Msg m) {
        m.setMsg(m.getMsg()+"--filter2");
    }
}

class FilterChain implements Filter{
    List<Filter> filters = new ArrayList<>();
    public FilterChain add(Filter f){
        filters.add(f);
        return this;
    }
    public void doFilter(Msg m){
        for (Filter f : filters) {
            f.doFilter(m);
        }
    }
}

当然有时候我们并不需要,消息经过整个责任链,有可能在第一个过滤器就因为数据不符合直接返回了。这种情况该如何实现呢?
我们需要修改一下Filter的doFiltervoid->boolean
具体代码如下

import java.util.ArrayList;
import java.util.List;

public class FilterMain {
    public static void main(String[] args) {
        Msg msg = new Msg();
        msg.setMsg("hello world");

        FilterChain fc = new FilterChain();
        fc.add(new Filter1()).add(new Filter2());
        fc.doFilter(msg);
        System.out.println(msg);
    }
}

class Msg{
    private String msg;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    @Override
    public String toString() {
        return msg;
    }
}

interface Filter{
    boolean doFilter(Msg m);
}

class Filter1 implements Filter{
    @Override
    public boolean doFilter(Msg m) {
        m.setMsg(m.getMsg()+"--filter1");
        return true;
    }
}

class Filter2 implements Filter{
    @Override
    public boolean doFilter(Msg m) {
        m.setMsg(m.getMsg()+"--filter2");
        return false;
    }
}

class FilterChain implements Filter{
    List<Filter> filters = new ArrayList<>();
    public FilterChain add(Filter f){
        filters.add(f);
        return this;
    }

    public boolean doFilter(Msg m){
        for (Filter f : filters) {
            if(!f.doFilter(m)){  // 重点:判断只要有一个doFilter返回false就直接return false,不在继续执行下面的Filter
                return false;
            }
        }
        return true;
    }

}

最后是模拟ServletFilter的实现:
首先需要了解一下java中的Filter帮我们做了哪些事。
首先是request进来会经过Filter1,Filter2,Filter3然后进入到Servlet。而Servlet返回的时候会经过Filter3,FIlter2,Filter1,最终返回给客户端。这里很关键的一件事是,我们只写了一个过滤器链,确能够以123的顺序对request进行过滤,以321的顺序对response进行过滤。这是如何做到的呢?
在这里插入图片描述
直接上代码

package com.zxh.design.filter;

import java.util.ArrayList;
import java.util.List;


/**
 * Created by zxh on 2022/1/10
 */
public class ServletFilterMain {

    public static void main(String[] args) {
        Request request = new Request();
        request.str = "request";
        Response response = new Response();
        response.str = "response";

        FilterChain chain = new FilterChain();
        chain.add(new Filter1())
             .add(new Filter2())
             .add(new Filter3());
        chain.doFilter(request,response);
        System.out.println(request.str);  // request--Filter1--Filter2--Filter3
        System.out.println(response.str);  // response--Filter3--Filter2--Filter1
    }

}

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

class Request{
    String str;
}

class Response{
    String str;
}

class Filter1 implements Filter{
    @Override
    public void doFilter(Request request, Response response, FilterChain chain) {
         request.str = request.str+"--Filter1";
         // 这里进行一个递归调用,为了保证request是正序,response是倒叙。
         // 对request的处理要放在chain.doFilter之前,对response的处理要放在之后
         chain.doFilter(request,response);
         response.str += "--Filter1"; // chain.doFilter执行结束后,response才有值,如果要对返回值进行处理需要在这里进行
    }
}

class Filter2 implements Filter{
    @Override
    public void doFilter(Request request, Response response, FilterChain chain) {
        request.str += "--Filter2";
        chain.doFilter(request,response);
        response.str += "--Filter2";
    }
}

class Filter3 implements Filter{
    @Override
    public void doFilter(Request request, Response response, FilterChain chain) {
        request.str += "--Filter3";
        chain.doFilter(request,response);
        response.str += "--Filter3";
    }
}

// 该类封装了过滤器链由doFilter方法进控制调用
class FilterChain{
    List<Filter> filters = new ArrayList<>();
    int index = 0;

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

    public void doFilter(Request request,Response response){
        if(index == filters.size()) return;
        Filter filter = filters.get(index);
        index++;
        filter.doFilter(request,response,this);
    }
}

在Filter接口的doFilter的中新增了FilterChain 参数取消了返回值。我们将过滤器链的调用全部交给FilterChain。当我们调用chain.doFilter(request,response);该方法就会帮我们调用当前Filter,并且index++将下标指向下一个Filter.

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值