Strategy pattern: swap behaviour
Put interchangeable algorithms behind one interface. A context delegates to the selected strategy instead of branching through a growing switch.
Watch it animatedStep through it, with the running line highlighted. Free with an account.The idea
Checkout is the context. It delegates the calculation to the IDiscountStrategy object it receives. Switching to NoDiscount changes the behaviour without adding a conditional to Checkout.
Code
class DiscountStrategy {
public:
virtual double apply(double subtotal) = 0;
virtual ~DiscountStrategy() = default;
};
class NoDiscount : public DiscountStrategy {
public:
double apply(double subtotal) override { return subtotal; }
};
class TenPercentOff : public DiscountStrategy {
public:
double apply(double subtotal) override { return subtotal * 0.9; }
};
class Checkout {
DiscountStrategy& discount;
public:
Checkout(DiscountStrategy& discount) : discount(discount) {}
double total(double subtotal) { return discount.apply(subtotal); }
};
int main() {
TenPercentOff ten;
Checkout checkout(ten);
cout << checkout.total(100) << "\n"; // 90
}from typing import Protocol
class DiscountStrategy(Protocol):
def apply(self, subtotal: float) -> float: ...
class NoDiscount:
def apply(self, subtotal: float) -> float: return subtotal
class TenPercentOff:
def apply(self, subtotal: float) -> float: return subtotal * 0.9
class Checkout:
def __init__(self, discount: DiscountStrategy):
self.discount = discount
def total(self, subtotal: float) -> float:
return self.discount.apply(subtotal)
checkout = Checkout(TenPercentOff())
print(checkout.total(100)) # 90.0interface IDiscountStrategy {
decimal Apply(decimal subtotal);
}
class NoDiscount : IDiscountStrategy {
public decimal Apply(decimal subtotal) => subtotal;
}
class TenPercentOff : IDiscountStrategy {
public decimal Apply(decimal subtotal) => subtotal * 0.9m;
}
class Checkout {
private readonly IDiscountStrategy discount;
public Checkout(IDiscountStrategy discount) { this.discount = discount; }
public decimal Total(decimal subtotal) => discount.Apply(subtotal);
}
var checkout = new Checkout(new TenPercentOff());
Console.WriteLine(checkout.Total(100m)); // 90Tips
- Use Strategy when several behaviours share one shape and the choice can vary. Keep each strategy focused on one algorithm.
- For only two tiny branches that never change, an interface and multiple classes may add needless complexity.
In the .NET library
Common examples include payment methods, shipping-cost rules, compression formats, and validation policies. Dependency injection can select a default strategy; a factory can select one from runtime input.