Originally published on phpdesignpatterns.dev — part of the PHP design patterns course. View this lesson on the original site.

Cases where a match beats an interface

Strategy is one of the most over-applied patterns. Two or three branches do not need an interface and three classes. Here are the cases where Strategy is the wrong move and what to do instead.

When Strategy is usually overkill

flowchart TD
  a{{"Two or three short branches total?"}}
  a -->|yes| m[match or if is clearer]
  a -->|no| b{{"Branches only differ by data not behaviour?"}}
  b -->|yes| d[Table lookup or value object]
  b -->|no| c{{"You need return values from every branch into caller?"}}
  c -->|yes| e[Consider other shapes first]
  c -->|no| ok[Revisit when pressure returns]

Overkill case 1 — Two simple branches

<?php

if ($user->isAdmin()) {
    return $this->fullReport();
}

return $this->summaryReport();

This is fine. It will still be fine when there are three branches. Don't introduce an interface for it.

Overkill case 2 — A match with one-line bodies

<?php

$rate = match ($currency) {
    'GBP' => 1.00,
    'EUR' => 1.18,
    'USD' => 1.27,
    default => throw new InvalidArgumentException("Unknown: {$currency}"),
};

Don't replace this with three classes. It is already the smallest possible expression of the variation. Promote to Strategy only if a body grows beyond one expression.

Overkill case 3 — Variation that lives in one place

If the branching exists in exactly one function and no other part of the codebase needs to know about the choice, splitting it across files just makes the code harder to find. Patterns are for recurring problems, not single-site ones.

Overkill case 4 — Branches that share more than they differ

<?php

if ($type === 'A') {
    $rows = $this->load('A');
    $rows = array_filter($rows, ...);
    $rows = array_map(..., $rows);
    return $this->format($rows);
}

if ($type === 'B') {
    $rows = $this->load('B');
    $rows = array_filter($rows, ...);
    $rows = array_map(..., $rows);
    return $this->format($rows);
}

The branches share 90% of their work. The "variation" is just the 'A' vs 'B' argument. Don't make this a Strategy — extract a helper that takes the type as a parameter.

How to recognise overkill before you commit to it

Before introducing Strategy, write down on paper:

  1. How many branches will exist after this change? Two or three is rarely worth an interface.
  2. Will more branches arrive in the next six months? If you can't think of a plausible one, you're solving an imaginary problem.
  3. What does the smallest version of this look like as a match? If match fits cleanly, it's the better answer.

If after that exercise you still want Strategy, you probably need it. If you only wanted it because patterns "feel professional", stop and use the simpler shape.

The alternative

When Strategy is overkill, the alternative is almost always: a match expression, an enum, or a small helper function. Those are not "lesser" choices — they're the appropriate tool for variation that hasn't earned an interface yet.

From PHP design patterns — Strategy: replacing branching with swappable behaviour