2021年4月30日 星期五

[設計模式] Simple Factory Pattern 簡單工廠模式 與 Strategy Pattern 策略模式 使用方式

先前閱讀設計模式,

通常讀了之後沒什麼感覺,無法產生共鳴,

更別說應用到實務上了。


但實際照著範例練習,

確實比較有一點和過去經驗連結的感覺,

現在開始會陸續地把練習時得到的聯想記錄下來,

希望如果有類似應用情境的人可以用得上。


未來相關文章主要是依照大話設計模式的章節安排去進行紀錄,

而這兩個模式一起寫是因為作者將之結合應用確實達到滿好的效果,

以收銀程式作為範例,

GitHub連結 (範例在Chapter_2.1-2.4)

CashSuper 為各種收銀演算法的父類別,

目前有三種收銀演算法 CashRebate、CashNormal、CashReturn

產生演算法物件的工廠 CashFactory,

包含所有演算法的框架 CashContext,

彼此之間的關係以我自己畫的類別圖來說明(還不太會畫,以我自己的理解去說明):





以上是同一隻練習程式寫成三種不同架構的類別圖,

我刻意把相同的部分置中對齊,

有沒有發現Strategy Pattern結合Simple Factory Pattern的UML和單獨使用Strategy Pattern的UML是相同的?

那是因為Strategy Pattern結合Simple Factory Pattern的時候,是把概念套用到了Context類別中的建構子,

而不是真正的把工廠類別再寫出來去使用(當然如果要再寫出來也是OK拉...)

補充說明一下圖中的User Vision是什麼意思:

"沒有視野代表不必include,不能夠new出這個物件,

因為必須要include 進來才能夠對該類別作操作。"

越少的include,也代表更低耦合的程式碼架構。


總結來說,

不同的Pattern使用起來會讓User 需要得到的視野不同,

如果視野太多太廣,一個類別內需要懂得其他類別太多(include),

就存在更高的耦合性,對於維護、擴充、再利用的情況就更加限制,

看到這邊應該還是一頭霧水吧?

我們再以表格來看看使用不同Pattern,User視野的比較:





有沒有發現,對於相同的一隻程式碼,

單獨使用Simple Factory Pattern時需要知道各種演算法的父類別(CashSuper)與工廠(CashFactory),

藉此封裝建立物件的過程。

單獨使用Strategy Pattern時,雖然能夠切換不同的策略方式,

但必須懂得能夠使用的演算法類別有哪幾個(CashNormal、CashRebate、CashReturn),

並透過容器(CashContext)去包裝。

結合Simple Factory Pattern與Strategy Pattern時,

使用者只需要知道CashContext即可,

大幅的簡化使用者與其他類別的耦合度(因為只需知道一個類別就能使用所有的功能)。


應用情境

對於機台開發的實務上來說,

非常適合用於初期研發的機台,

因為初代機台可能會需要對選用的某一項硬體設備進行不同品牌的試用,

舉例來說:

我們的機台會用到光學探頭,

而光學探頭有好幾家的品牌提供試用,

每一家廠商都提供不一樣的功能特色,

開發初期就必須考慮我們可能會因為不同的情況替換不同廠牌的光學探頭,

這時候就非常適合把這些不同品牌的光學探頭寫成結合Simple Factory Pattern與Strategy Pattern的方式,

在主程式只需要切換一個地方,馬上就能夠把這台機台使用的光學探頭切換成另一品牌,

甚至是測試用的模擬類別,

對於測試、初期研發非常有用。


依目的來看待模式使用時機

如果想集中封裝建立物件的過程,就使用Simple Factory。

如果想彈性切換相同功能、不同類別的物件,就使用Strategy。

3 則留言:

  1. 作者已經移除這則留言。

    回覆刪除
  2. 邊看說明邊看github上的code還蠻清楚的。
    對我來說就是比較不會變化的話我會用簡單工廠。單純的封裝起來。
    如果時常變化的話我會用策略+簡單工廠 將變化封裝起來。

    回覆刪除
    回覆
    1. 沒錯,也可以從另一個角度看,
      只要是"工具類"的類別都可以用簡單工廠模式封裝物件建立的過程,
      至於是有替換需求的,則可以結合策略模式進行低耦合的架構撰寫。

      刪除

社會新鮮人如何投資?

我的觀點是,在 沒有很多 本錢 的情況下, 別寄望每個月幾千元放到股票或者最近很夯的高股息ETF就能讓你致富, 先投資自己,讓自己的本業收入提高吧。