职责链模式
在之前的观察者模式实战中,我们说过并不是所有的状态监控场景都适用于观察者模式,比如最近在看的Android项目中,当一个页面的组件很多时,对同一个时间的响应上,Android设计了一种传递机制,当我们合理利用后可以让我们想要的组件来响应事件,而如果是观察者模式,那么所有的组件都会响应。所以我们今天就来看这一种新的设计模式--职责链模式,也称为责任链模式。
场景分析
那么现在让我们来看一下这样一种需求:在Android或者类前端中,除了要处理很多事件之外,还有很多的情况是UI组件的重叠,在设计上就可能导致很多问题:
多重响应:如果重叠的每一个组件都订阅了触摸事件,在不进行其他的限制的情况下,当用户触摸时,就会出现每个UI组件都会响应事件,这个在大部分情况都是不允许的
顶部响应:由于UI组件的重叠,上层处理事件后如果就结束了,很有可能导致下面的组件没有办法收到事件而无法响应
不可控:由于组件都是事件的订阅者,地位相同,在收到事件后分别作出反应。而事件的接受顺序是不可控的,这就导致组件可能不是按照预想的方式进行下去。并且如果我们想在事件到达某一层后停止也没有办法做到。
那么我们可以看到,在这种情况下,仅仅使用观察者模式并不能解决问题,我们更需要关注的是事件的传递。那么我们来看一下职责链模式是如何解决这个问题的。
职责链模式
我们在观察者模式中提到的设计模式图中,就描绘过职责链模式也属于行为型设计模式,如果不了解行为型模式的可以参考之前的文章,按照设计模式的分析顺序,我们来看一下职责链模式的意图、动机、结构和代码实现。
意图
职责链模式是这样一种设计模式,设计一种处理链,允许请求沿着处理链进行发送。收到请求后,每个处理者都可以对请求进行处理,并选择是否将请求传递给下一个处理者,或者封装新的请求传递下去。
动机
我们在上面描述的组件响应事件就是职责链应用的典型场景。在我们构造UI组件时,一般来说都是都是一种树形结构,那么事件的传递其实就是从叶子到根的一条链路,如下图:
由于UI的树形结构,我们很容易根据需求设计出职责链模式。但是在其他不明显的业务上,就不一定第一时间想到职责链模式。我们来分析这样一个需求,那就是在web服务里面增加用户验证。
一般来说,我们很容易想到定义一个验证方法,然后接受用户的登录请求,然后进行验证。这个并不难,但是这时需求增加了一项,需要先去另一个系统认证,如果验证成功了,再进行加下来的验证。这个也不难,我们可以在验证方法中加入这个逻辑。系统用了一段时间后,发现验证方法太弱了,需要增加额外的检查,这时我们只能继续在验证方法中添加,然后后面发现验证的效率不够高,需要增加缓存来提高响应速度。这时我们还是会想到直接在验证方法里面加入逻辑即可。
这时我们就发现这个设计有问题了,因为随着需求的不断变更,我们的验证方法变得越来越复杂,即使我们将代码拆分,也会让其他人阅读和维护变得困难。更重要的是,当我们打算复用这段代码的时候,我们必须再按照需求去一一检查我们的逻辑,将可用的代码复制过去,而且如果不是我们自己写的,我们很有可能会被其中的逻辑依赖搞晕。
而这就是设计模式的用途了,代码随着不断发展问题变得越来越多,说明我们之前的设计就有问题。那我们尝试用上面的职责链模式来重构我们的这部分逻辑:
首先定义一条链路,也就是将检查步骤的逻辑抽象成相同的结构,然后将步骤注册到链路中。
然后定义每一步的参数是请求数据,每个处理者处理完后都会返回一个状态来确定是继续处理还是终止。
这样的话,就变成了下面的结构:
那么我们看一下有没有解决上面的问题,第一就是需求不断变更,在这种情况下我们只需要增加一个步骤并将其注册到链路中,而整个链路的逻辑不需要任何的变化。然后就是复用,我们可以直接将链路复制过去,然后将我们需要的步骤移过去,由于每个步骤是完全对等的,所以就不存在什么逻辑依赖了。
结构
经过上面的分析,我们就很容易得到职责链的数据结构:
处理者:也就是处理请求的具体逻辑,并且返回值需要能够决定请求是否继续传递。
然后就是我们的客户端负责生成链路并注册处理者。整个职责链模式的结构非常简单,重要的是这个设计理念。
代码实现
职责链模式在很多语言和框架设计上都有所体现,比如UI组件设计,过滤器等。这里我们就简单实现一下职责链模式(使用的是Java,其他语言可自行设计):
首先检查业务逻辑,是否可以将请求处理逻辑拆分成相同结构的方式
定义处理者接口
定义两种处理者,一种处理完继续传递,一种处理完结束。
定义客户端,组装职责链并处理请求
代码见:https://github.com/soolaugust/design-pattern-demo/tree/master/src/chain/of/responsibility
总结
这一篇我们对职责链模式有了基本的了解,能够在遇到相似的场景时,考虑是否使用职责链模式。在没有真实的项目经验下,了解这些就可以了。
在下一篇我们会进一步讲解职责链模式的内容,并讲解如何来使用职责链模式。
版权声明: 本文为 InfoQ 作者【soolaugust】的原创文章。
原文链接:【http://xie.infoq.cn/article/a19a3a0351ac355bb6177e6a7】。未经作者许可,禁止转载。
评论