Introduction
Strategy and Command are both behavioral design patterns that wrap behavior inside objects, but they solve different problems. Strategy lets you select an algorithm's implementation at runtime, while Command turns a request or action into a standalone object that can be executed, queued, logged, or undone.
Cricket analogy: Strategy is like a captain swapping in a different bowling plan (pace versus spin) depending on the pitch, choosing the algorithm at match time; Command is like recording each bowling change as a formal decision in the team log that can later be reviewed, replayed for analysis, or reversed if it didn't work.
Explanation
The Strategy pattern defines a family of interchangeable algorithms, each implementing a common interface, and lets a context object delegate work to whichever strategy is currently assigned. This avoids large conditional blocks that branch on type or mode, and it lets new algorithms be added without touching the context's code. The Command pattern instead encapsulates a request as an object with an execute() method (and often an undo() method), decoupling the object that invokes an action from the object that knows how to perform it. Commands can be stored in queues, logged for auditing, or kept in a history stack to support undo/redo, which is something Strategy does not address since strategies are stateless algorithm choices rather than reversible actions.
Cricket analogy: Strategy defines interchangeable bowling plans, like a pace attack or a spin attack, each following the same 'deliver an over' contract, letting the captain swap plans without redesigning the match; Command instead wraps a specific bowling change as a recorded decision with an execute step, and unlike a strategy swap, that decision can be logged in the team's post-match review or reconsidered if the captain wants to 'undo' the tactical shift.
Example
from abc import ABC, abstractmethod
# --- Strategy pattern ---
class DiscountStrategy(ABC):
@abstractmethod
def apply(self, price: float) -> float:
...
class NoDiscount(DiscountStrategy):
def apply(self, price: float) -> float:
return price
class PercentageDiscount(DiscountStrategy):
def __init__(self, percent: float) -> None:
self.percent = percent
def apply(self, price: float) -> float:
return price * (1 - self.percent / 100)
class ShoppingCart:
def __init__(self, strategy: DiscountStrategy) -> None:
self.strategy = strategy # chosen at runtime
def checkout(self, price: float) -> float:
return self.strategy.apply(price)
cart = ShoppingCart(PercentageDiscount(20))
print(cart.checkout(100.0)) # 80.0
cart.strategy = NoDiscount()
print(cart.checkout(100.0)) # 100.0
# --- Command pattern ---
class Command(ABC):
@abstractmethod
def execute(self) -> None:
...
@abstractmethod
def undo(self) -> None:
...
class Light:
def __init__(self) -> None:
self.is_on = False
def turn_on(self) -> None:
self.is_on = True
def turn_off(self) -> None:
self.is_on = False
class TurnOnCommand(Command):
def __init__(self, light: Light) -> None:
self.light = light
def execute(self) -> None:
self.light.turn_on()
def undo(self) -> None:
self.light.turn_off()
living_room_light = Light()
command = TurnOnCommand(living_room_light)
history: list[Command] = []
command.execute()
history.append(command)
print(living_room_light.is_on) # True
history.pop().undo()
print(living_room_light.is_on) # FalseAnalysis
Both patterns are behavioral because they focus on how responsibilities are delegated at runtime rather than how objects are constructed or structured. Strategy is chosen when you need to swap an algorithm (sorting, pricing, validation) without changing the calling code, and it typically has no notion of history or reversal. Command is chosen when you need to treat an action as a first-class object: for queuing tasks, implementing undo/redo, logging operations, or supporting macro commands that batch several commands together. A common point of confusion is that both patterns 'wrap behavior in an object', but Strategy answers 'how should this be done' while Command answers 'what action should be performed and can it be reversed'.
Cricket analogy: Both patterns are about in-game delegation, not squad construction: Strategy is chosen when swapping bowling plans (pace versus spin) without changing how the captain calls the over, with no notion of reversing a delivery once bowled; Command is chosen when the team wants each tactical decision, like a bowling change, treated as a loggable, reviewable, possibly reversible action, useful for post-match analysis or in-game reviews via DRS-like reconsideration.
Key Takeaways
- Strategy encapsulates interchangeable algorithms behind a common interface, selected at runtime.
- Command encapsulates a request as an object with an execute() method, optionally supporting undo().
- Strategy eliminates large conditional branches for selecting behavior.
- Command enables queuing, logging, and undo/redo of actions.
- Both are behavioral patterns focused on delegating responsibility, not object creation or structure.
Practice what you learned
1. What problem does the Strategy pattern primarily solve?
2. What method does a Command object typically implement to perform its action?
3. Which capability is most closely associated with the Command pattern rather than Strategy?
4. In the Strategy pattern, how does the context object use a strategy?
5. Both Strategy and Command are classified as which type of design pattern?
Was this page helpful?
You May Also Like
Observer Pattern
A behavioral pattern where a subject maintains a list of observers and notifies them automatically of any state changes.
Design Patterns Overview
An introduction to the Gang of Four design patterns and their three categories: Creational, Structural, and Behavioral.
Single Responsibility and Open/Closed Principles
Learn to split classes by responsibility and extend behavior with polymorphism instead of editing existing code.
Related Reading
Related Study Notes in Software Engineering
Browse all study notesMicroservices Study Notes
Software Architecture · 30 topics
Software EngineeringTesting & TDD Study Notes
Software Testing · 30 topics
Software EngineeringDesign Patterns Study Notes
Software Design · 30 topics
Software EngineeringGit & Version Control Study Notes
Bash · 40 topics
Software EngineeringSystem Design Study Notes
Architecture · 40 topics