100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Python

Strategy and Command Patterns

Two behavioral patterns: Strategy swaps interchangeable algorithms at runtime; Command encapsulates a request as an executable object.

Design Patterns — BehavioralIntermediate11 min readJul 8, 2026
Analogies

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

python
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)  # False

Analysis

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

Was this page helpful?

Topics covered

#Python#SoftwareEngineeringStudyNotes#SoftwareEngineering#StrategyAndCommandPatterns#Strategy#Command#Patterns#Explanation#StudyNotes#SkillVeris