8

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

 3 years ago
source link: http://www.cnblogs.com/techflow/p/13729056.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

链式方法也叫做流式方法,是一种相对比较新的概念,经常在流式计算或者类似的场景当中出现。举个例子,我们之前讲过的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 -


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK