Patterns: behavior · 3 MIN READ
Command: represent an action as a value
Make actions queueable or reversible without claiming every effect can be undone.
Make actions queueable or reversible without claiming every effect can be undone. Command packages an operation and its receiver into a value that can be executed later. Trace the worked Go example, then compare the benefit with the cost before applying this design to your own project.
Behavioral pattern · A MAP OF THE IDEA
- Create action with receiver and arguments
- Execute through a command value
- Restore prior state only where valid
Useful when
- Actions need queuing, history or local undo
- The invoker should not know receiver details
Watch out
- Undo assumes a defined state history
- Durable commands need explicit schemas
Implementation & operation cost: Medium
Fit depends on the task
Editorial suitability, not benchmarks or a universal ranking. Styles describe different axes and can be combined.
The design decision
Command packages an operation and its receiver into a value that can be executed later. It can support local undo when enough previous state is retained. Sending an email or charging a remote payment is not reversed by merely invoking a method named Undo.
A complete Go example
Read this program from the entry point and follow the calls shown in the diagram. The output is included at the end so you can check the behavior without a compiler.
package main
import (
"fmt"
)
type Rename struct {
target *string
next, previous string
done bool
}
func (c *Rename) Do() {
if c.done {
return
}
c.previous = *c.target
*c.target = c.next
c.done = true
}
func (c *Rename) Undo() {
if !c.done {
return
}
*c.target = c.previous
c.done = false
}
func main() {
name := "draft"
c := &Rename{target: &name, next: "report"}
c.Do()
fmt.Println(name)
c.Undo()
fmt.Println(name)
}
// Output:
// report
// draft
Rename captures the receiver, requested name and old name. Do is guarded against repetition; Undo restores the prior value. This assumes no independent mutation between execution and undo and one owner of the receiver.
Tradeoffs and the simpler alternative
For durable queues, serialize a command schema and validate it on receipt; a closure cannot survive process exit. Undo of external work often needs a compensating business action with its own possible failures. Use a direct function for one immediate action.
TAKE THIS WITH YOU
Captures an action and the data needed to execute it. For durable queues, serialize a command schema and validate it on receipt; a closure cannot survive process exit. Undo of external work often needs a compensating business action with its own possible failures. Use a direct function for one immediate action.
Check your understanding
Which statement best describes Command: represent an action as a value?
Go to the source
Progress stays in this browser. No account needed.