Strategy Pattern
Concept Definition
Strategy lets you place interchangeable algorithms behind one common interface. The object that uses the algorithm does not need to know which exact algorithm it received. It simply calls the interface.
A useful analogy is choosing a route in a maps app. The app can use fastest route, shortest route, or avoid-tolls route without rewriting the whole navigation screen.
Why It Matters
Beginners often write one large method with many flags: if (type == "student"), else if (type == "member"), else if (type == "holiday"). That method becomes fragile because every new algorithm requires editing the same old code. Strategy moves each algorithm into its own class, so the caller stays stable.
Strategy is also a clean way to practice dependency injection. You pass behavior into an object instead of hard-coding the behavior inside it.
Syntax Block
class Strategy {
public:
virtual ~Strategy() = default; // base cleanup
virtual double run(double x) const = 0; // algorithm contract
};
class Context {
public:
explicit Context(std::unique_ptr<Strategy> s); // inject algorithm
};
Explained Code
Example: Discount Strategy
#include <memory> // std::unique_ptr
class DiscountStrategy {
public:
virtual ~DiscountStrategy() = default; // safe base deletion
virtual double apply(double price) const = 0; // algorithm contract
};
class NoDiscount : public DiscountStrategy {
public:
double apply(double price) const override { return price; } // unchanged price
};
class StudentDiscount : public DiscountStrategy {
public:
double apply(double price) const override { return price * 0.80; } // 20 percent off
};
class Checkout {
private:
std::unique_ptr<DiscountStrategy> discount; // owns selected strategy
public:
explicit Checkout(std::unique_ptr<DiscountStrategy> selected)
: discount(std::move(selected)) {} // move ownership into object
double total(double price) const { return discount->apply(price); } // delegate
};
Checkout does not contain discount rules. It only knows that a discount strategy can apply a price calculation.
Key Points / Rules
- Use Strategy when several algorithms share the same purpose.
- The context class should depend on the strategy interface, not concrete strategy classes.
- Each strategy class should stay small and focused.
- Strategy can reduce large
if/elseorswitchstatements. - Strategy adds extra classes, so use it when the behavior truly varies.
Common Mistakes
- Keeping the old conditional block anyway. If
Checkoutstill checks every discount type, you have not gained the main benefit. - Making strategies too broad. A strategy interface should represent one family of algorithms.
- Sharing mutable strategy state carelessly. If many objects share one strategy object, be clear whether it is immutable.
- Using inheritance for data instead of behavior. Strategy is about swappable behavior, not just storing different fields.
Quick Check
- Which class should know the discount formula:
CheckoutorStudentDiscount? - What design smell suggests Strategy might be useful?
Viva Answer
Strategy replaces conditional algorithm selection with polymorphism. It lets a class use an algorithm through an interface while concrete strategy classes provide the actual behavior.