14、Cahin of Responsibility 责任链 COR设计模式

责任链模型初体现

  • 通过上面的代码可以看到帖子处理器会对帖子进行不同的过滤, 我们可以把一种过滤方法对应为一个过滤器, 并且向上抽取出过滤器接口.

 public class Demo2 {
     public static void main(String[] args) {
         String msg = "大家好 :), <script>haha</script> 我要说超级敏感的话";
         MsgProcessor mp = new MsgProcessor();
         mp.setMsg(msg);
         System.out.println(mp.process());
    }
 }
 ​
 class MsgProcessor{
     private String msg;
     private Filter[] filters = {new HtmlFilter(), new SensitiveFilter(), new ExpressionFilter()};
     public String process(){
         for(Filter f : filters){
             msg = f.doFilter(msg);
        }
         return msg;
    }
 ​
     public String getMsg() {
         return msg;
    }
 ​
     public void setMsg(String msg) {
         this.msg = msg;
    }
 }
 //过滤器接口
 interface Filter{
     public String doFilter(String s);
 }
 //处理html标签
 class HtmlFilter implements Filter{
     @Override
     public String doFilter(String s) {
         return s.replace("<", "[").replace(">", "]");
    }
 }
 //处理敏感词句
 class SensitiveFilter implements Filter{
     @Override
     public String doFilter(String s) {
         return s.replace("敏感", "正常");
    }
 }
 //处理表情
 class ExpressionFilter implements Filter{
     @Override
     public String doFilter(String s) {
         return s.replace(":)", "^_^");
    }
 }
  • 上面的代码已经具备了责任链的模型. 在帖子发送到服务器的过程中, 它将依次经过3个过滤器, 这三个过滤器就构成一条过滤器链.

  • image-20200729150037295

  • 下面我们考虑, 如果我们要在帖子处理过程中加入新的过滤器链条, 加在原链条的末尾或中间, 该怎么办呢?

  • 消息经过过滤器链条的过程会得到处理, 我们可以把过滤器链条看成一个过滤器, 让他也实现Filter接口, 那么就可以在一条过滤链中任意加入其他过滤器和过滤链了.

  • 下面的代码实现了过滤链FilterChain, 用过滤链替代原来的MsgProcessor.

 public class Demo3 {
     public static void main(String[] args) {
         String msg = "大家好 :), <script>haha</script> 我要说超级敏感的话";//待处理的帖子
         FilterChain fc1 = new FilterChain();//创建一条过滤器链1
         fc1.add(new HtmlFilter())
                .add(new SensitiveFilter());//往过滤器链1中添加过滤器
 ​
         FilterChain fc2 = new FilterChain();//创建一条过滤器链2
         fc2.add(new ExpressionFilter());//往过滤器链2中添加过滤器
 ​
         fc1.add(fc2);//把过滤器链2当作过滤器添加到过滤器链1中,(过滤器链实现了Filter接口)
 ​
         msg = fc1.doFilter(msg);//使用过滤器链1对帖子进行过滤
         System.out.println(msg);
    }
 }
 ​
 class FilterChain implements Filter{
 ​
     private List<Filter> list = new ArrayList<>();
 ​
     public FilterChain add(Filter filter){
         this.list.add(filter);
         return this;
    }
 ​
     @Override
     public String doFilter(String s) {
         for(Filter f : list){
             s = f.doFilter(s);
        }
         return s;
    }
 }
 ​
 class HtmlFilter implements Filter{
     @Override
     public String doFilter(String s) {
         return s.replace("<", "[").replace(">", "]");
    }
 }
 ​
 class SensitiveFilter implements Filter{
     @Override
     public String doFilter(String s) {
         return s.replace("敏感", "正常");
    }
 }
 ​
 class ExpressionFilter implements Filter{
     @Override
     public String doFilter(String s) {
         return s.replace(":)", "^_^");
    }
 }
 ​
 interface Filter{
     public String doFilter(String s);
 }

更精巧设计, 展现责任链模式

  • 在继续优化之前, 我们考虑更现实的需求, 一个请求(发出一个帖子)作为数据报发送给服务器, 服务器除了需要对请求进行过滤外, 还需要给出响应, 并且可能要对响应也进行处理. 如下图所示

image-20200729145957738

  • 当一个消息(包含请求体和响应体)发往服务器时, 它将依次经过过滤器1, 2, 3. 而当处理完成后, 封装好响应发出服务器时, 它也将依次经过过滤器3, 2, 1.

  • 大家可能会觉得有点像栈结构, 但是像归像, 这一逻辑应该如何实现呢?

  • 首先我们可以让过滤器持有过滤器链的引用, 通过调用过滤器链依次执行每个过滤器. 为了能让过滤器依次执行每个过滤器, 过滤器会持有一个index序号, 通过序号控制执行顺序. 至于后面对response的倒序请求, 则通过方法返回实现. 这部分设计纯用文字难以讲清, 请务必看下面的代码和代码后的分析, 配图.

  • 这个部分是责任链的精髓了, 懂了这部分代码, 看Web开发中的过滤器源码就没压力了.

 public class Demo4 {
     public static void main(String[] args) {
         String msg = "大家好 :), <script>haha</script> 我要说超级敏感的话";//以下三行模拟一个请求
         Request request = new Request();
         request.setRequestStr(msg);
 ​
         Response response = new Response();//响应
 ​
         FilterChain fc = new FilterChain();//过滤器链
         HtmlFilter f1 = new HtmlFilter();//创建过滤器
         SensitiveFilter f2 = new SensitiveFilter();
         ExpressionFilter f3 = new ExpressionFilter();
         fc.add(f1);//把过滤器添加到过滤器链中
         fc.add(f2);
         fc.add(f3);
 ​
         fc.doFilter(request, response, fc);//直接调用过滤器链的doFilter()方法进行处理
         System.out.println(request.getRequestStr());
    }
 }
 ​
 interface Filter{
     public void doFilter(Request request, Response response, FilterChain fc);
 }
 ​
 class FilterChain implements Filter{
 ​
     private List<Filter> list = new ArrayList<>();
 ​
     private int index = 0;
 ​
     public FilterChain add(Filter filter){
         this.list.add(filter);
         return this;
    }
 ​
     @Override
     public void doFilter(Request request, Response response, FilterChain fc) {
         if(index == list.size()){
             return;//这里是逆序处理响应的关键, 当index为容器大小时, 证明对request的处理已经完成, 下面进入对response的处理.
        }
         Filter f = list.get(index);//过滤器链按index的顺序拿到filter
         index++;
         f.doFilter(request, response, fc);
    }
 ​
 }
 ​
 class HtmlFilter implements Filter{
     @Override
     public void doFilter(Request request, Response response, FilterChain fc) {
         request.setRequestStr(request.getRequestStr().replace("<", "[").replace(">","]"));
         System.out.println("在HtmlFilter中处理request");//先处理request
         fc.doFilter(request, response, fc);//调用过滤器链的doFilter方法, 让它去执行下一个Filter的doFilter方法, 处理response的代码将被挂起
         System.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

航迹者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值