大家好,欢迎大家阅读设计模式专题。
今天我们继续介绍新的设计模式,和上次的链式模式不同,这一次要介绍的责任链模式不仅仅在Python当中有,在很多其他的语言当中同样支持,比如Java。Python和Java当中的这个设计模式是完全一样的,没有任何区别。
和之前介绍的设计模式相比,今天介绍的设计模式同样不难。我们非常容易想明白它的原理。
责任链
在我们日常的开发当中,经常会有上下游的依赖,比如当前我们需要开发一份新的数据,需要用到上游的某一份老数据才能生成。这时候需要我们写一个接口,然后上游也随之改造,把它们的新数据写到我们这个接口来。
这就带来了一个问题,也就是上下游耦合的问题,如果下游有一天变动了,上游也需要随着变动。如果是一对一的可能还好,如果一个上游存在多个下游,那么这会是一件很麻烦的事。每一个下游变动了,上游都需要调整。举个最简单的例子,比如下游想要做一个AB测试,想要一半流量进入A机器,一半流量进入B机器。这都需要上游配合。
这当然是很不合理的,在实际当中上游的数据可能是另外一个团队负责的,他们只对数据质量负责,并不一定会愿意配合。并且这样的配合也会导致效率低下。
为了解决这个问题,有了责任链的设计模式。我们把下游的响应方存入一条链路当中,上游在发送请求时不感知下游的接收情况以及相应细节。
说白了,用一句话来概括,就是用链路把下游串起来。我们来看一张图就明白了:
我们把图中的采购人员看成是数据上游的话,它只管提出请求,具体响应的人他是不知道的。根据申请金额的不同,审批的人员也会不一样。但是只会有一个人审批,如果当前人员审批不了就会上报,也就是交由后面一个节点处理。不得不说是非常形象了。
代码实现
那怎么把下游用一条链路串起来呢,其实也很简单,我们可以利用抽象类来实现。比如说我们可以这样:
class Handler:
def __init__(self, next=None):
self.next = next
def handle(self, request):
res = self.do_handle(request)
if not res and self.next:
self.next.handle(request)
def do_handle(self, request):
pass
这里的handler就是实现链式调用的关键,在handle当中会首先自己进行处理,如果处理失败那么会调用下一个handle来进行。Handle类中do_handle的方法是抽象方法,我们希望每一个继承Handle的子类都能实现自己的do_handle逻辑。
所以如果是用Java来实现的话,会非常清晰,因为在Java当中有抽象类的相关概念。由于Python原生没有抽象类的相关设定,所以会稍微隐晦一些,但是逻辑是也一样的。
在我们代码实现之前,我们先来介绍一个无关紧要的包。这个包就是Python当中的six,其实这个包也不算是无关紧要,通过它可以写出兼容Python2和Python3的代码。但是实际上由于现在Python2已经快扫进历史的垃圾堆了,所以有没有这个包都没有关系,这里我们还是尊重原作者的代码,保留了这么一个包。我们用这个包作为注解,完成了抽象基类的构建。
抽象基类
首先