命令 (Command)

★★★★Studied

FromDesign Patterns (GoF)大話設計模式

📚 From the Books

命令 (Command)ConceptBehavioral

把「一個請求」連同它的參數封裝成獨立物件,讓你能把操作當資料傳遞、排隊、記錄與 undo。核心是讓發出請求的 invoker 不知道、也不在乎真正執行的是誰。

🧠 When to Use

TIP

訊號:你想把「要做的動作」存起來、排成佇列、寫進 log、之後重放或反悔(undo/redo),而不是當下立刻寫死地呼叫某個方法。

⚖️ Structure & Variants

經典版 — Command 介面 + Invoker,含 undo
interface Command { fun execute(); fun undo() }

class Light { var on = false }

class TurnOn(private val light: Light) : Command {
    override fun execute() { light.on = true }
    override fun undo()    { light.on = false }
}

class Remote {                              // ← invoker,不知道具體命令
    private val history = ArrayDeque<Command>()
    fun press(cmd: Command) { cmd.execute(); history.addLast(cmd) }
    fun undoLast()          { history.removeLastOrNull()?.undo() }
}

val light = Light()
Remote().apply { press(TurnOn(light)); undoLast() }   // on=false
  • Remote 只認得 Command;換行為 = 換傳進去的命令物件。
函數式版 — 命令就是一個 closure
  • 不需要 undo 時,命令可以退化成一個 () -> Unit,把參數包進 closure 即可。
  • 一旦要 undo/redo 或序列化,才值得升級成帶 execute/undo 的具名物件。
巨集命令 — 把多個命令組成一個
  • MacroCommand 內含一串 Commandexecute 依序跑、undo 逆序回放,本身也是 Command(Composite 的味道)。

⚠️ Misuse & Anti-patterns

🔑 Takeaways

✍️ My Notes

No notes yet — jot your takeaways or Q&A here.

📖 Further Reading