• 《图解设计模式》读书笔记6-2 Chain of Responsibility模式


    1. 简介

    Chain of Responsibility模式是责任链模式,模式的核心就是转移责任。就好比你要去政府部门办事,A部门说你去B部门问问,B部门说你去C部门问问,C部门说我们不管...在找到正确的部门解决问题之前,这些部门一直在踢皮球。

    在程序中,确实需要这样的场景:将多个对象组成一个责任链,一个请求过来了,按照它们在责任链上的顺序一个一个找出到底由谁来负责

    这个模式的好处在于弱化请求方和处理方的关联关系,让双方都可以成为独立复用的组件。

    2. 示例程序

    类图

    代码

    Trouble类是表示问题的类,其属性nubmer是问题编号。

    Support以及其子类表示解决问题的类,Support是抽象父类,具体的Support类表示解决特定问题的类。

    public class Trouble {
        private int number;             // 问题编号
        public Trouble(int number) {    // 生成问题
            this.number = number;
        }
        public int getNumber() {        // 获取问题编号
            return number;
        }
        public String toString() {      // 代表问题的字符串
            return "[Trouble " + number + "]";
        }
    }
    //解决问题的抽象父类
    public abstract class Support {
        private String name;
        private Support next;
        public Support(String name) {
            this.name = name;
        }
        public Support setNext(Support next) {
            this.next = next;
            return next;
        }
        //定义解决问题的步骤
        // 其中使用了抽象方法resolve,这个方法由子类实现,这是Template Method方法的体现。
        public void support(Trouble trouble) {
            if (resolve(trouble)) {
                done(trouble);
            } else if (next != null) {
                next.support(trouble);
            } else {
                fail(trouble);
            }
        }
        public String toString() {
            return "[" + name + "]";
        }
        protected abstract boolean resolve(Trouble trouble);
        protected void done(Trouble trouble) {
            System.out.println(trouble + " is resolved by " + this + ".");
        }
        protected void fail(Trouble trouble) {
            System.out.println(trouble + " cannot be resolved.");
        }
    }
    //什么问题都不解决
    public class NoSupport extends Support {
        public NoSupport(String name) {
            super(name);
        }
        protected boolean resolve(Trouble trouble) {     // 解决问题的方法
            return false; // 自己什么也不处理
        }
    }
    // 可以解决编号小于limit的问题
    public class LimitSupport extends Support {
        private int limit;                              
        public LimitSupport(String name, int limit) {   // 构造函数
            super(name);
            this.limit = limit;
        }
        protected boolean resolve(Trouble trouble) {    // 解决问题的方法
            if (trouble.getNumber() < limit) {
                return true;
            } else {
                return false;
            }
        }
    }
    //解决编号为奇数的问题
    public class OddSupport extends Support {
        public OddSupport(String name) {                // 构造函数
            super(name);
        }
        protected boolean resolve(Trouble trouble) {    // 解决问题的方法
            if (trouble.getNumber() % 2 == 1) {
                return true;
            } else {
                return false;
            }
        }
    }
    //只能解决编号为number的问题
    public class SpecialSupport extends Support {
        private int number;                                
        public SpecialSupport(String name, int number) {    // 构造函数
            super(name);
            this.number = number;
        }
        protected boolean resolve(Trouble trouble) {        // 解决问题的方法
            if (trouble.getNumber() == number) {
                return true;
            } else {
                return false;
            }
        }
    }
    public class Main {
        public static void main(String[] args) {
            Support noSupportMan   = new NoSupport("noSupportMan");
            Support lt2Man = new LimitSupport("lt2Man", 2);
            Support specialFor5Man = 
                new SpecialSupport("specialFor5Man", 5);
            Support lt10Man   = new LimitSupport("lt10Man", 10);
            Support oddMan    = new OddSupport("oddMan");
            Support lt15Man    = new LimitSupport("lt15Man", 15);
            // 一层一层深入设置职责链条
            noSupportMan
                .setNext(lt2Man)
                .setNext(specialFor5Man)
                .setNext(lt10Man)
                .setNext(oddMan)
                .setNext(lt15Man);
            // 解决各种问题
            for (int i = 0; i < 17; i++) {
                noSupportMan.support(new Trouble(i));
            }
        }
    }
    //结果
    [Trouble 0] is resolved by [lt2Man].
    [Trouble 1] is resolved by [lt2Man].
    [Trouble 2] is resolved by [lt10Man].
    [Trouble 3] is resolved by [lt10Man].
    [Trouble 4] is resolved by [lt10Man].
    [Trouble 5] is resolved by [specialFor5Man].
    [Trouble 6] is resolved by [lt10Man].
    [Trouble 7] is resolved by [lt10Man].
    [Trouble 8] is resolved by [lt10Man].
    [Trouble 9] is resolved by [lt10Man].
    [Trouble 10] is resolved by [lt15Man].
    [Trouble 11] is resolved by [oddMan].
    [Trouble 12] is resolved by [lt15Man].
    [Trouble 13] is resolved by [oddMan].
    [Trouble 14] is resolved by [lt15Man].
    [Trouble 15] is resolved by [oddMan].
    [Trouble 16] cannot be resolved.
    
    

    3. 模式的角色和类图

    角色

    • Handler(处理者):定义了处理请求的接口,这个角色知道下一个Handler是谁,如果自己处理不了就会交给下一个Handler处理。本例中,由Support类扮演此角色。
    • ConcreteHandler(具体的处理者):实现了具体的处理方法。由NoSupport、LimitSupport、OddSupport、SpecialSupport扮演此角色。
    • Client(请求者):向处理者发送问题请求的角色,本例中由Main类扮演此角色。

    类图

    4. 思路拓展

    • 弱化了发出请求的人和处理请求的人的关系

    • 可以动态改变职责链

    • 专注于自己的工作

    • 模式的缺点:责任被传递,请求会延迟

  • 相关阅读:
    IE8使用chrome内核渲染
    JS中的call()方法和apply()方法用法总结(挺好 转载下)
    解决雷达图文字显示不全问题
    echarts legend文字配置多个颜色(转)
    vue中Axios的封装和API接口的管理
    echarts 折线拐点收藏
    echarts 折线图自定义颜色与修改legend颜色
    MUI框架 按钮点击响应不好的问题解决办法
    ECharts将折线变平滑和去掉点的属性
    单例模式——创建型模式01
  • 原文地址:https://www.cnblogs.com/qianbixin/p/10953138.html
Copyright © 2020-2023  润新知