Command Pattern 與 Strategy Pattern 的差異

有一天...

被問了一個問題,在實作登入功能時,如果要支援不同的登入方式(ex: FB/google/twitter),那麼該使用Strategy Pattern還是Command Pattern?

對於design pattern本身就不算瞭解,被問到這問題真的是完全無法解釋。開始了漫長的辜狗之旅,但看了一串又一串的討論還是無法解釋之後,決定配合字面定義來看:

COMMAND: 命令

命令通常有—發號命令者、接受命令者(負責決定如何執行)、命令、命令執行對象。比如說Gwen叫Howie去打掃(家裡),Gwen是發號命令者,命令的內容有 1.任務:打掃 2.任務執行者:Howie 3.任務對象:家裡。發號命令者可以決定他要執行什麼命令,對誰執行或是更改任務。比如說Gwen也可以選擇要他家的貓Uno去打掃(變更接受命令者),或是Gwen可以叫Howie去打掃隔壁老王的家(更變執行對象),又或是可以叫Howie把家裡重新裝潢一次(變更任務)。

STRATEGY: 策略

根據形勢發展而制定的行動方針或方法,目的是完成一個明確的任務。策略說的是不同物件(形勢發展),執行同樣的動作時(如前例:打掃家裡),會採取不同的路徑(行動方針,策略)。之前的例子用策略的角度來看就是:同樣是打掃,Howie與Uno打掃的方式就完全不一樣(實際上,Uno是一隻貓)

我們來看一下Wiki上面對於Command & Strategy的design pattern的解說:

Command pattern is a behavioral design pattern in which an object is used to represent and encapsulate all the information needed to call a method at a later time.

Formally speaking, the strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable.

還是不太懂?

Command pattern強調的是發號命令者接受命令者命令命令執行對象之間的關係,command本身只是一個資訊傳遞的載體,負責把發號命令者的命令傳遞給接受者。而Strategy pattern是用來讓單一任務可以有不同的解法。

回到登入的問題,假設我們系統需要提供使用者FB/twitter/google三種不同帳號登入,那麼我們該用command還是strategy?

如果我們用command pattern,那麼我們需要一種命令:登入,而命令執行者有三個:FB登入小幫手、twitter登入小幫手以及google登入小幫手。如果是用strategy pattern的話,我們需要三種不同的策略:FB登入/twitter登入/google登入。

這裡就會發現,就算登入的方式變得再怎麼多種,命令還是只有一種,只是一直增加不同的命令執行者。當然我們可以把命令變成三種:登入FB/登入twitter/登入google,然後再用三個命令執行者來處理這三種命令(考量到command pattern裡的command其實只負責資訊的傳遞,任務的處理還是需要由命令執行者來做),但這樣子似乎又有點過度分工。前面的敘述可以知道command pattern裡面的command儲存了三個面向的資料:1.任務 2.誰執行 3.對誰執行,而在實作登入功能時其實有兩個是不需要的:1.任務:很單純的就是登入 3.執行的對象是系統也不會變動,唯一會變的就是不同的命令執行者而已。

而如果是用strategy pattern的話,在實作時則是寫好各種不同的登入strategy,再依照使用者的選擇呼叫相對應的strategy來處理即可。依照這樣的分析下來,不同的登入方式應該用strategy pattern即可解決,也因此,passportjs用的是strategy pattern。

參考資料

沒有留言:

張貼留言