Android优雅编程-职责链模式

最近在维护公司项目的时候,发现了一个前辈写的一段代码,大家可以先看一下,这里为隐去了具体的实现,代码如下:

private void cmdHandler(int cmd, String data) {
        switch (cmd) {
            case CMD1:
                //具体业务 ....
                //to do ....
                break;
            case CMD2:
                //具体业务 ....
                //to do ....
                break;
            case CMD3:
                //具体业务 ....
                //to do ....
                break;
            case CMD4:
                //具体业务 ....
                //to do ....
                break;
            case CMD5:
                //具体业务 ....
                //to do ....
                break;
            case CMD6:
                //具体业务 ....
                //to do ....
                break;
            case CMD7:
                //具体业务 ....
                //to do ....
                break;
            case CMD8:
                //具体业务 ....
                //to do ....
                break;
            case CMD9:
                //具体业务 ....
                //to do ....
                break;
            case CMD10:
                //具体业务 ....
                //to do ....
                break;
            case CMD11:
                //具体业务 ....
                break;
            //后面还有很多
        }
    }```
随着公司业务的发展具体的`CMD*`的数量还在不断的增长中,由于该类是公共服务中的一部分,每增加一个相关的业务就需要增加一个`CMD`,团队有N个程序员小哥,不同的小哥添加了不同的`CMD`而且“上”完就走,生活经验告诉我们大家一起用的东西都肯定不会有什么好结果,这个模块一样没逃脱这个悲惨的命运,现在这个类已经有几千行,充斥着迷一样的业务实现交织在一起。
![timg.jpeg](http://upload-images.jianshu.io/upload_images/1857802-2873ae9b6122c12a.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/440)

我觉得这个图片非常直观的展现这个类也表达了我的心情,再不重构这颗雷迟早会炸,只是时间问题,作为一个有情怀的程序员😊,我怎么会让这种事情发生,下面直奔主题!

这里用到了设计模式中的 “_职责链模式(Chain of Responsibility)_ ”
>责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
`引用:《Java与模式》`

需要把每一个`CMD`命令抽象出来,实现成单独的职责处理对象,然后为它们提供一个公共的、抽象的父职责对象,这样就可以动态地组合职责链,当收到`CMD`命令的时候,命令会沿着链传递,传递到对应的处理者,就会被处理消耗,每个`CMD`都有具体的`Handler`处理者,实现业务代码的解耦。

首先抽象处理者
```java
public abstract class RobotHandler<D> {
    protected RobotHandler<D> nextHandler;

    public RobotHandler() {
    }

    public abstract void handle(D data);

    public void setNextHandler(RobotHandler<D> handler) {
        this.nextHandler = handler;
    }
}```

下面创建几个具体的处理者
* CMD1
```java
public class HandleCMD1 extends RobotHandler<String> {

    @Override
    public void handle(int cmd,String data) {
        if (cmd == 1) {
            handleDeviceState(data);
        } else if (nextHandler != null) {
            nextHandler.handle(data);
        }
    }

    private void handleDeviceState(String data) {
        S.i("I'm HandlerCMD1 handled" + data);
    }
}
  • CMD2
public class HandleCMD2 extends RobotHandler<String> {

    @Override
    public void handle(int cmd,String data) {
        if (cmd == 2) {
            handleDeviceState(data);
        } else if (nextHandler != null) {
            nextHandler.handle(data);
        }
    }

    private void handleDeviceState(String data) {
        S.i("I'm HandlerCMD2 handled" + data);
    }
}

使用方式

RobotHandler<String> handler1 = new HandleCMD1();
RobotHandler<String> handler2 = new HandleCMD2();
handler1.setNextHandler(handler2);
.
.
.

private void cmdHandler(int cmd, String data) {
     handler1.handle(cmd,data);
}
       

到这里为止在网上搜到的大多数讲指责链模式的文章都是差不多这样实现了,看看那几十个HandleCMD每一都要自己动手去设置setNextHandler,且不说一手抖设错了怎么办,因为是链式结构,可能我们偶尔还需要根据使用频率将这一堆handler调整下顺序,有没有一群草泥马从眼前奔腾而过的赶脚?

为了赶走“草泥马”继续优化


public class RobotHandlerManager<D> {
    private RobotHandler<D> handler;

    private RobotHandlerManager(RobotHandler<D> h) {
        this.handler = h;
    }

    public void handle(int cmd,D data) {
        handler.handle(cmd,data);
    }

    public static class HandlersBuilder<D> {
        private RobotHandler<D> header;
        private RobotHandler<D> tail;

        public HandlersBuilder() {
            header = null;
            tail = null;
        }

        public HandlersBuilder<D> addHandler(RobotHandler<D> handler) {
            if (header == null) {
                this.header = handler;
                this.tail = handler;
            } else {
                this.tail.setNextHandler(handler);
                this.tail = handler;
            }
            return this;
        }

        public RobotHandlerManager<D> build() {
            return new RobotHandlerManager<>(header);
        }
    }
}

使用方式

RobotHandlerManager<String> handlerManager = new RobotHandlerManager.HandlersBuilder<String>()
                .addHandler(new HandleCMD1())
                .addHandler(new HandleCMD2())
                .build();

private void cmdHandler(int cmd, String data) {
     handlerManager.handle(cmd,data);
}

运行结果:

屏幕快照 2017-03-14 下午3.31.00.png

从此整个世界都清净了!
demo已上传github

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,392评论 25 707
  • 什么是css hack 由于不同厂商的流览器或某浏览器的不同版本(如IE6-IE11,Firefox/Safari...
    tiandashu阅读 170评论 0 0
  • 从西安回家的第三天,我已经守着她许多小时了,记录着她抽搐的频率,由一个多小时到半个小时,到二十分钟,再到十五分...
    ___indulgence__阅读 247评论 0 0