zoukankan      html  css  js  c++  java
  • 设计模式之美学习-行为型-责任链模式(二十九)

    什么是责任链模式

    解释1:将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。

    解释2:在职责链模式中,多个处理器(也就是刚刚定义中说的“接收对象”)依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式。

    二种表现形式

    表现形式1:通过链头开始执行,如果不能处理依次往下传递,直到能处理为止

    表现形式2:通过链头开始执行 依次传递到联调尾

    实现方式一

    第一版

    //抽象的Handler
    public abstract class Handler {
        protected Handler successor = null;
    
        public void setSuccessor(Handler successor) {
            this.successor = successor;
        }
    
        public abstract void handle();
    }
    //链条上的处理器a
    public class HandlerA extends Handler {
        @Override
        public boolean handle() {
            //标识自己是否能处理
            boolean handled = false;
            //... 省略处理逻辑 处理成功handled改为true
            //如果不能处理交给下一个handel处理
            if (!handled && successor != null) {
                //交给下一个handle处理
                successor.handle();
            }
        }
    }
    //联调上的处理器B
    public class HandlerB extends Handler {
        @Override
        public void handle() {
            //标识自己是否能处理
            boolean handled = false;
            //... 省略处理逻辑 处理成功handled改为true
            //如果不能处理交给下一个handle处理
            if (!handled && successor != null) {
                successor.handle();
            }
        }
    }
    
    /**
     * HandlerChain 是处理器链,从数据结构的角度来看,它就是一个记录了链头、链尾的链表。
     * 其中,记录链尾是为了方便添加处理器
     */
    public class HandlerChain {
        private Handler head = null;
        private Handler tail = null;
    
        public void addHandler(Handler handler) {
            handler.setSuccessor(null);
            if (head == null) {
                head = handler;
                tail = handler;
                return;
            }
    
            tail.setSuccessor(handler);
            tail = handler;
        }
    
        public void handle() {
            if (head != null) {
                //从链头依次往下传递
                head.handle();
            }
        }
    }
    
    // 使用举例
    public class Application {
        public static void main(String[] args) {
            //管理链表
            HandlerChain chain = new HandlerChain();
            //添加处理器
            chain.addHandler(new HandlerA());
            chain.addHandler(new HandlerB());
            //执行处理
            chain.handle();
        }
    }

    第二版

    上面的代码会有问题 如果不熟悉代码结构的人,定义一个handler很容易在handler方法 不能处理漏掉调用下一个处理器, 还有就是上面的handler方法存在重复 所以将调用代码抽象到父类

    public abstract class Handler {
        protected Handler successor = null;
    
        public void setSuccessor(Handler successor) {
            this.successor = successor;
        }
    
        //定义在父类 final修饰不能重写
        public final void handle() {
            //调用 doHanle 由子类实现  模板模式
            boolean handled = doHandle();
            if (successor != null && !handled) {
                successor.handle();
            }
        }
        //抽象的定义 模板模式
        protected abstract boolean doHandle();
    }
    
    public class HandlerA extends Handler {
        /**
         * 只关注自身的处理逻辑
         * @return
         */
        @Override
        protected boolean doHandle() {
            boolean handled = false;
            //...
            return handled;
        }
    }
    
    public class HandlerB extends Handler {
        /**
         * 只关注自身的处理逻辑
         * @return
         */
        @Override
        protected boolean doHandle() {
            boolean handled = false;
            //...
            return handled;
        }
    }
    
    // HandlerChain和Application代码不变

    第三版

    采用非链表的方式来定义 采用数组的方式 使结构更简单

    //定义handler
    public interface IHandler {
        boolean handle();
    }
    
    //处理器a
    public class HandlerA implements IHandler {
        @Override
        public boolean handle() {
            boolean handled = false;
            //...
            return handled;
        }
    }
    
    //处理器b
    
    public class HandlerB implements IHandler {
        @Override
        public boolean handle() {
            boolean handled = false;
            //...
            return handled;
        }
    }
    
    public class HandlerChain {
        //通过集合维护处理器
        private List<IHandler> handlers = new ArrayList<>();
    
        public void addHandler(IHandler handler) {
            this.handlers.add(handler);
        }
    
        public void handle() {
            //遍历所有处理器 依次执行 直到其中一个能处理
            for (IHandler handler : handlers) {
                boolean handled = handler.handle();
                if (handled) {
                    break;
                }
            }
        }
    }
    
    // 使用举例
    public class Application {
        public static void main(String[] args) {
            HandlerChain chain = new HandlerChain();
            chain.addHandler(new HandlerA());
            chain.addHandler(new HandlerB());
            chain.handle();
        }
    }

    敏感字过滤实战

    未使用设计模式

    public class SensitiveWordFilter {
      // return true if content doesn't contain sensitive words.
      public boolean filter(Content content) {
        if (!filterSexyWord(content)) {
          return false;
        }
    
        if (!filterAdsWord(content)) {
          return false;
        }
    
        if (!filterPoliticalWord(content)) {
          return false;
        }
    
        return true;
      }
    
      private boolean filterSexyWord(Content content) {
        //....
      }
    
      private boolean filterAdsWord(Content content) {
        //...
      }
    
      private boolean filterPoliticalWord(Content content) {
        //...
      }
    }

    缺点 :如果需要增加一种过滤方式 就需要增加一个方法 和增加一个if判断 违反开闭原则

    使用了设计模式

    //抽象的过滤器
    public interface SensitiveWordFilter {
        boolean doFilter(Content content);
    }
    
    /**
     * 涉黄过滤
     */
    public class SexyWordFilter implements SensitiveWordFilter {
        @Override
        public boolean doFilter(Content content) {
            //是否包含敏感字
            boolean legal = true;
            //...
            return legal;
        }
    }
    
    // PoliticalWordFilter、AdsWordFilter类代码结构与SexyWordFilter类似
    
    //责任链管理类
    public class SensitiveWordFilterChain {
        private List<SensitiveWordFilter> filters = new ArrayList<>();
    
        public void addFilter(SensitiveWordFilter filter) {
            this.filters.add(filter);
        }
    
        // return true if content doesn't contain sensitive words.
        public boolean filter(Content content) {
            for (SensitiveWordFilter filter : filters) {
                if (!filter.doFilter(content)) {
                    return false;
                }
            }
            return true;
        }
    }
    
    public class ApplicationDemo {
        public static void main(String[] args) {
            SensitiveWordFilterChain filterChain = new SensitiveWordFilterChain();
            filterChain.addFilter(new AdsWordFilter());
            filterChain.addFilter(new SexyWordFilter());
            filterChain.addFilter(new PoliticalWordFilter());
            //传入发表内容 判断是否可发表
            boolean legal = filterChain.filter(new Content());
            if (!legal) {
                // 不发表
            } else {
                // 发表
            }
        }
    }

    优点:如果需要增加一种过滤方式 只需要新增一个filter类 注册到chain 

    源码中的应用

    Servlet Filter

    它可以实现对 HTTP 请求的过滤功能,比如鉴权、限流、记录日志、验证参数等等。因为它是 Servlet 规范的一部分,所以,只要是支持 Servlet 的 Web 容器(比如,Tomcat、Jetty 等),都支持过滤器功能

    具体从ApplicationFilterChain 开始看

    Spring MVC拦截器

    具体从:HandlerExecutionChain开始看

  • 相关阅读:
    Windows下安装并设置Redis
    Android平台相机接口的应用
    Struts(十五):主题
    Struts(十四):通用标签-form表单
    Struts(十三):通用标签
    Struts(十二):异常处理:exception-mapping元素
    Struts(十一):OGNL表达式(二)
    Struts(十):OGNL表达式(一)
    A*算法
    Centos:如何查找安装的jdk的目录
  • 原文地址:https://www.cnblogs.com/LQBlog/p/12705875.html
Copyright © 2011-2022 走看看