Java设计模式之责任链模式

一、责任链模式的定义
二、责任链模式的使用场景
三、责任链模式UML类图
四、责任链模式具体实例
五、责任链模式代码实现

  1. 抽象领导者
    2.具体领导者,继承自抽象领导者类
    六、责任链模式优缺点
    七、总结
    之前计划先把设计模式学完,但是感觉设计模式毕竟这么多种,粗略过一遍又不太好,所以决定还是先学自己需要学的Android知识点,在学习的过程中遇到了哪种设计模式再来学习,感觉这样效率会高一点,而且更容易自己理解。昨天在研究Android事件分发机制时发现Android事件分发机制是一种典型的责任链模式。于是特意在去学习责任链模式,所以就有了这篇文章,这文章基本都是参照《Android源码设计模式解析与实战》一书。

一、责任链模式的定义
使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。

二、责任链模式的使用场景
多个对象可以处理同一请求,但具体由哪个对象处理则在运行时动态决定。
在请求处理者不明确的情况下向多个对象中的一个提交一个请求。
需要动态指定一组对象处理请求。

三、责任链模式UML类图


20180619210346398.jpeg

示意图:


20180906092810465.gif

四、责任链模式具体实例
看了这么多概念性的东西总觉得优点懵逼,接下来引用书上的一个例子,感觉特别简单明了。
栗子:小群某天接到通知说要去国外进修学习新技术,小群听到这消息心中暗喜,表面上还是假装很镇定,于是她特意问了一下公司是否报销,在得到了肯定的答案之后小群背上背包踏上了去国外的进修之旅。小群这趟去国外学习一趟花了近10万块,于是小群上班后的第一天就是找公司报销,向组长申请报销费用,组长一看这么大一笔钱,他哪里有这个权限,他手里最多才可以批1000块,于是组长就拿着票据去找部门主管,主管一看要报这么多钱,自己权限内只能批1万以下的费用,这完全超出了自己的权限范围呀,于是又只得去找上一级也就是经理,经理一看,我也只能批5万以下的费用啊。于是二话不说拿着票据直接奔向了老板的办公室,让老板去处理小群的这个请求。上面的这个情景就是一个责任链的小栗子,每一个人,准确的说是每一类人代表这条链上的一个节点,小群是请求的发起者,而老板也就是我们的大BOSS则是处于链条顶端的类,小群从链的底端开始发出一个申请报账的请求,首先由组长处理该请求,组长比对后发现自己权限不够,于是将该请求转发给位于该链中下一个节点的主管,主管比对后发现自己权限也不够,又只能将该请求转发给经理,而经理同样权限不够,毕竟10万块的大数目只有老板能处理,于是最后经理又将请求转发给了老板,这样层层转达直到请求被处理。从中大家可以看到一个显而易见的事,就是至始至终小群只与组长产生了关联,后面具体由谁处理报销的票据,小群并不关心,小群只关心自己的票据(请求)有没有被成功处理。责任链模式在这里很好的将请求的发起者和处理者解耦。接下来我们用代码来实现这一过程。

五、责任链模式代码实现

  1. 抽象领导者
/**
 * 抽象的领导类,即UML图中的Hanlder
 */

public abstract class Leader {

    protected Leader nextHandler;//上一级领导(处理者),UML图中的successor

    /**
     * 处理报账请求
     * @param money 报账额度
     *  申明为final,子类无法重写
     */
    public final void handleRequest(double money){
        if(money<=limit()){
            handle(money);
        }else{
            if(null!=nextHandler){//有上一级处理者
                nextHandler.handleRequest(money);
            }else{
                Log.e(getClass().getSimpleName(),"没有领导能批复你的票据报销啦,自己去报销吧!");
            }
        }
    }

    /**
     * 自身能批复的报账额度
     * @return 额度
     */
    public abstract double limit();

    /**
     * 处理报账行为
     * @param money 报账额度
     */
    public abstract void handle(double money);
}

在这个抽象的领导类中只做了两件事,一是定义了两个抽象接口方法来确定一个领导者应有的行为和属性,二是声明了一个处理报账请求的方法来确定当前领导是否有能力处理报账请求,如果没有这权限,则将该请求转发给上级领导处理。接下来是各个具体的领导类的实现。

2.具体领导者,继承自抽象领导者类

/**
 * 组长
 */

public class GroupLeader extends Leader {
    @Override
    public double limit() {
        return 1000;
    }

    @Override
    public void handle(double money) {
        Log.e(getClass().getSimpleName(),"组长批复报销了你的"+money+"元");
    }
}
/**
 * 主管
 */

public class Director extends Leader {
    @Override
    public double limit() {
        return 10000;
    }

    @Override
    public void handle(double money) {
        Log.e(getClass().getSimpleName(),"主管批复报销了你的"+money+"元");
    }
}
/**
 * 经理
 */

public class Manager extends Leader {
    @Override
    public double limit() {
        return 50000;
    }

    @Override
    public void handle(double money) {
        Log.e(getClass().getSimpleName(),"经理批复报销了你的"+money+"元");
    }
}
/**
 * 大BOSS
 */

public class Boss extends Leader {
    @Override
    public double limit() {
        return 999999;
    }

    @Override
    public void handle(double money) {
        Log.e(getClass().getSimpleName(),"老板批复报销了你的"+money+"元");
    }
}

具体领导类创建后,小群从组长开始发起请求申请报账,代码如下:

public class XiaoQun extends BaseActivity {


    @Override
    protected int getLayoutId() {
        return R.layout.chain_of_responsibility_model_activity;
    }

    @Override
    protected void initView() {
        setToolBarTitle("责任链模式");
    }

    @Override
    protected void init() {
        GroupLeader groupLeader = new GroupLeader();
        Director director = new Director();
        Manager manager = new Manager();
        Boss boss = new Boss();

        //设置上一级领导(处理者)对象
        groupLeader.nextHandler = director;
        director.nextHandler = manager;
        manager.nextHandler = boss;

        //发起报账申请
        groupLeader.handleRequest(100000);
    }
}

最后运行结果如下:

可以看到最后是BOSS处理了小群的报账申请,而且也只有BOSS才有这个权限处理,但是这里小群在申请的时候却只和组长进行了交流,降低了耦合度,这也是责任链模式的优点。当然这里我们代码也可以直接越过组长找主管或者经理或者直接找BOSS报账也是可以的,这也是责任链模式的灵活之处,请求的发起可以从责任链的任何一个节点开始,同时也可以改变责任链内部传递的规则,如主管不在,我们完全可以跨过主管直接将请求转送给经理。

六、责任链模式优缺点
优点

  1. 降低耦合度:客户端不需要知道请求由哪个处理者处理,而处理者也不需要知道处理者之间的传递关系,由系统灵活的组织和分配。
  2. 良好的扩展性:增加处理者的实现很简单,只需重写处理请求业务逻辑的方法。
    缺点
  3. 请求会从链头发出,直到有处理者响应,在责任链比较长的时候会影响系统性能。
  4. 请求递归,调试排错比较麻烦。

七、总结
对于责任链中的一个处理者对象,其只有两个行为,一是处理请求,二是将请求转送给下一个节点,不允许某个处理者对象在处理了请求后又将请求转送给上一级节点的情况。对于一条责任链来说,一个请求最终只有两种情况,一是被某个处理对象所处理,另一个是所有对象均未对其处理,对于前一种情况我们称该责任链为纯的责任链,对于后一种情况我们称为不纯的责任链,在实际应用中,我们所见到的责任链模式大多为不纯的责任链。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容