­

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

  • 2020 年 9 月 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 –