設計模式第二篇,鏈式方法模式

TechFlow2019發表於2020-09-25

大家好,這是設計模式專題的第二篇文章,我們一起來聊聊鏈式方法的設計模式。

鏈式方法也叫做流式方法,是一種相對比較新的概念,經常在流式計算或者類似的場景當中出現。舉個例子,我們之前講過的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 -

相關文章