设计模式第二篇,链式方法模式

879 阅读4分钟

大家好,这是设计模式专题的第二篇文章,我们一起来聊聊链式方法的设计模式。

链式方法也叫做流式方法,是一种相对比较新的概念,经常在流式计算或者类似的场景当中出现。举个例子,我们之前讲过的pyspark当中就用了这个模式,比如当我们处理rdd的时候,经过转换操作我们得到的仍然是一个rdd,直到遇到执行操作位置。dataframe也是一样的,我们转换阶段的操作我们可以连在一起写。

我们来看一个例子:

df.select("xx", "yy").withColumn("id", monotonically_increasing_id()).join(df2, ["id"], "left").join(df3, ["id"])

看出来了吗,因为中间的这些操作返回的结果都是dataframe,所以我们可以把它们写成一串。也就是流式操作的写法,Java8的一个重大特性就是支持了流式操作。所以当时Java8出来之后很多程序员很不适应,因为不习惯写这样的流式操作。

流式方法的好处非常明显,我们可以把一系列操作写在一行当中,通过一行代码实现一连串操作。但是Python的原生语言特性是不支持流式操作的,所以才需要通过设计模式来使它支持。这里的设计模式也非常简单,就只是利用了Python面向对象的实现方式而已。

返回其他对象

想要实现链式方法大概有两种方式,其实也不难理解,大家应该很容易想到。

第一种方式就是我们在方法当中return另外一个对象,这样我们在运行方法之后就可以继续调用实例的其他方法了。我们来看段代码:

class Person:

    def __init__(self, name, action):
        self.name = name
        self.action = action

    def do_action(self):
        print(self.name, self.action.name, end=' ')
        return self.action

这是一个Person的类,其中在init方法当中有一个action的参数。这个action明显是另外一个实例,我们在调用do_action的时候,会返回这个action。那么很明显,我们可以直接访问action的相关操作。

假设action这个实例当中有一个方法叫做operate,那么我们这个调用链路就可以写成:

action = Action()
person = Person('chengzhi', action)
person.do_action().operate()

这是一种实现方式,也就是在一个方法当中返回另外一个对象,这样我们可以继续调用返回对象的方法。除了这个方法之外,我们还可以返回自己。这种用法看起来比较少见,但是却是实实在在可行的。

返回self

我们之前在介绍Python面向对象当中相关概念的时候,曾经讲解过我们约定俗成需要在实例的方法当中放置一个参数self。这个参数self的作用和Java当中的this是一样的,只不过我们在Java当中隐去了这个变量,而在Python当中把它实实在在地写了出来。

这个self和this的用法都是一样的,就是实例自身的一个指针或者是引用。这样我们就可以在实例方法内部来调用实例中的其他一些变量。和Java当中的return this用法一样,我们在Python当中也可以返回self,因为self和类外部创建的实例是完全一样的。既然完全一样,那么我们自然也可以通过函数进行返回。

所以我们还可以这么写:

class Action:

    def __init__(self, name):
        self.name = name

    def amount(self, val):
        print(val, end=' ')
        return self

    def stop(self):
        print('end, stop')

我们看下amount这个方法,在这个方法当中我们返回的结果是self,也就是返回了实例本身。这样做的目的很简单,就是为了实现链式调用。

我们把调用的代码写出来:

action = Action('record')
action.amount().stop()

由于amount返回的结果就是实例本身,也就是代码中的action,所以我们继续调用stop方法是完全可行的,这并不违反语法规则。所以在函数当中返回实例自身也可以实现链式调用,这是我们刚才提到的第二种方法。

我们可以把这两种方法结合起来,自己根据实际的需要定义需要的链式操作。比如如果我们把刚才说的这两个类写在一起的话,我们可以变成这样:

action = Action('action')
person = Person('person', action)
person.do_action().amount('5m').stop()

当然,如果你愿意还可以定义更多,但总体来说实现的两种方法就在这里了。

我是承志,衷心祝愿大家每天都有所收获。如果还喜欢今天的内容的话,请来一个三连支持吧~(点赞、关注、转发

原文链接,求个关注

本文使用 mdnice 排版

- END -