設計模式筆記—Command Pattern

Command Pattern 是一個簡單到另你懷疑這算不算一種模式的模式
主要的形制大致上如下:

// Command.cs
interface Command {
void Execute();
}

實際上就是個只有一個執行方法的介面

以上面的 Command 介面為例,只要是實做 Command 介面的類別
呼叫它的 Execute 方法就會執行一連串的指令

這也能算得上是一種模式嗎?

善用介面

實際上 Command Pattern 就是利用了介面隱藏細節的特性
以最開始的 Command 介面為例子
對外部程式而言,只知道 Command 有一個 Execute 方法可以執行,並不知道實際上執行了什麼
透過這樣的特性就可以將多個 Command 串起來執行

相關的使用案例像是資料庫的遷移 (Migration)
如果有使用後端框架的經驗,應該都看過類似的東西:

class Migration_202301201330 : Migration {
public void Up() {
// ...
}

public void Down() {
// ...
}
}

透過實作或繼承 Migration 這個介面或是抽象類別,再定義資料庫更新版本和降版的相關操作
這其實就是 Command Pattern 的應用

在執行 Migration 的程式中,並不知道每個 Migration 做了什麼事情
但是它很明確的執行了「更新版本」的動作
必要時,還可以直接執行「降版」的動作

思考模式的概念

Command Pattern 透過統一的介面或抽象類別
讓程式在設計上可以善用像是 List 或是 Map 等資料結構進行管理與使用
這就是 Command Pattern 的強大之處

如果是會使用介面和抽象類別的朋友,或許在不知不覺中就已經用到這個模式了

介面或者抽象類別可以作為是一種抽象概念
Command Pattern 就是利用了這種抽象的概念來設計程式

前面提過的 Migration 就屬於一種概念
在執行資料庫遷移時,只要知道有哪些 Migration 可以執行退回就好
實際上每個 Migration 下了哪些 SQL 指令並不是執行資料庫遷移要關注的事情
按照這個思維,就會發現 Migration 這個介面或抽象類別出現了

Undo 功能

無暇的程式碼—敏捷完整篇 書中有提過 Command Pattern 實做 Undo 的部份
試想一下 Word 或是一些繪圖軟體的上一步下一步功能,為什麼不同性質的操作可以統一退回或復原呢?
實際上就是使用了 Command Pattern

即使操作的性質不同,只要實作介面,然後定義好相應操作的執行流程以及退回流程
對外部的程式而言,他們都是一樣的東西,都可以執行跟退回

前面舉的 Migration 的例子就有 Undo 的功能,只是叫做 Down 而已

結語

作為 無暇的程式碼—敏捷完整篇 書中第一個介紹的設計模式
這是最簡單而且概念最好懂的模式了
以入門來說,Command Pattern 正好可以作為練習使用介面或抽象類別的題材
學習用抽象概念去思考設計,而非一直使用代表實體的 class

後記

當我回頭去看過去寫的 Command Pattern 時,發現內容有夠少 XD
看起來就只是把書上的內容刪減然後改個寫法而已

有一點經驗之後,當我重看書時,就有了不同的體會
設計模式不單單只是照著模式走,而是應該思考為何要用這個模式,使用這種設計的理由

最初是因為看到有關重構的東西而去找書來學
但現在我認為,重構並不是什麼要特別學的東西,設計才是
只不過在追求良好設計的途中會驅使工程師重構,以維持軟體品質
良好的設計可以避免開發上不必要的開銷,並減少軟體維護需要付出的成本

更新

  • 2023-02-26
    更改區段標題 模式的設計思維思考模式的概念

    當初在寫的時候沒有意識到自己用了不正確的詞來下標題
    設計模式只是從過去的經驗歸納出來而已,講設計思維感覺比較怪
    所以改成 思考模式的概念 ,以自己的想法來嘗試解釋模式