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


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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM