Originally published on phpdesignpatterns.dev — part of the PHP design patterns course. View this lesson on the original site.
Signals that say "do it now"
The hardest part of using design patterns well is knowing when to actually reach for them. Here are the signals that mean Strategy is the right call right now — not "maybe someday".
Pressure check — when Strategy earns its keep
flowchart TD
a{{"Long if or switch with genuinely different work per branch?"}}
a -->|no| x[Prefer helpers match or small functions]
a -->|yes| b{{"New cases arrive without rewriting old ones?"}}
b -->|no| x
b -->|yes| c{{"Each branch could be a named domain class?"}}
c -->|yes| ok[Strategy is a strong candidate]
c -->|no| x
Strong signals — apply Strategy
- A function has a long
if/elseiforswitchwhere each branch holds genuinely different logic. - The set of branches grows over time as new business cases arrive.
- Adding a new branch means opening a long file and reading the others first to make sure you don't break them.
- A reviewer has asked "are you sure this doesn't conflict with the case above?" more than once.
- The branches have different inputs and outputs in spirit (e.g. one strategy needs a country, another doesn't), and the function fakes uniformity by accepting nullable parameters.
- You can name each branch with a domain noun (
LoyaltyPlusDiscount,NextDayShipping) — that's the strategy class title falling out of the requirements.
Soft signals — consider Strategy, but check first
- A small set of branches (two or three) where each one is non-trivial. Often Strategy is overkill here; revisit when a fourth branch arrives.
- A
matchexpression that's growing.matchis fine until the bodies stop fitting on one line each. - Code that "feels duplicated" across branches but isn't quite. Sometimes the right move is a helper, not a Strategy.
Bonus signal — testability
If the test for a single branch looks like "construct the whole feature, set everything else aside, and assert on this one path" — that's the function asking to be split. Strategy makes the test setup match the test scope.
What "the right call" actually feels like
After applying Strategy correctly, the calculator class is short, each rule's class is short, the test for a rule is short, and adding a new rule is a new file and a one-line update to the picker. Nothing in the existing code has to change. That's the win.
If after applying Strategy your code is more files but no easier to change, you applied it for the wrong reason. Lesson 2.12 is about exactly that case.
From PHP design patterns — Strategy: replacing branching with swappable behaviour