DEV Community

Cover image for Design Patterns by Purpose: The Strategy Pattern in Frontend Life (Part 3)
Anju Karanji
Anju Karanji

Posted on • Edited on

Design Patterns by Purpose: The Strategy Pattern in Frontend Life (Part 3)

You've tamed structure (Module) and domesticated creation (Factory). Next up: behavior.

Consider a payment processor that needs different personalities (credit card, PayPal, crypto, bank transfer, gift card). Left alone, it turns into an if/else hydra. The Strategy Pattern trims that chaos: you define a small, stable interface for the operation (say process, validate, or charge) and pass in interchangeable implementations at runtime. Call sites stay consistent; only the strategy changes. Result: fewer branches, cleaner tests, and new variants without touching the core. Swap, don't sprawl.

Cat Behaviors: The Furry Problem

trategy Pattern UML — BaseCat with StreetCat, HouseCat (necktie), Maneki-neko, and RoboCat. Behaviors via Eat/Sound/Move strategies.

Meet Cat, our base class.
Now the variants: StreetCat, HouseCat, ManekiNeko, HelloKitty (famously… silent).

Hard-coding eat(), meow(), and move() into Cat breaks half the family—some behave differently, some don’t meow at all. Copy-pasting those methods into every subclass? Hairball city.

Enter Strategy: pull -> eat, sound, and move into small, swappable objects with the same interface. Compose each cat with the behaviors it actually needs at runtime. New cat? Meet RoboCat—USB-C-powered, doesn’t eat, outputs a synthetic meow, and yes, it flies. You just plug in eatBehavior: none, soundBehavior: synth, and moveBehavior: thrusters. No base-class surgery, no if/else hairballs—just composition that feels like a firmware upgrade.

A real-world pass: CollapsiblePanel with pluggable behaviors

Time to leave the cat café and touch UI. The panel’s structure stays boring on purpose; the behavior gets swapped in.

You ship a solid CollapsiblePanel, and suddenly it’s everywhere. Marketing wants color + sparkle on click. Settings wants non-clickable panels. The dashboard wants panels sorted by priority. Sound familiar? This is where the Strategy Pattern earns its keep: don’t fork your component or stuff it with if/else. Make it behavior-agnostic and accept tiny “strategies” for clicks, sorting—whatever you need.

Think of it this way: the panel is the car; strategies are the drivers. The car exposes the wheel and pedals; the driver decides how to drive. Your panel exposes markup and state; strategies decide what to do.

You can create small strategy functions for different behaviors:

// Strategy objects const clickStrategies = { colorSparkle: { onClick: (id) => addSparkleEffect(id), getStyle: (id) => ({ backgroundColor: 'lightblue', transition: 'all 0.3s' }) }, disabled: { onClick: () => {}, // No-op getStyle: () => ({ opacity: 0.6, pointerEvents: 'none' }) } }; const sortStrategies = { priority: (panels) => [...panels].sort((a, b) => a.priority - b.priority), alphabetical: (panels) => [...panels].sort((a, b) => a.title.localeCompare(b.title)), }; // The panel stays behavior-agnostic const CollapsiblePanel = ({ id, title, children, clickStrategy = clickStrategies.disabled }) => { return ( <div> <div onClick={() => clickStrategy.onClick(id)} style={clickStrategy.getStyle(id)} className="panel-header" > {title} </div>  <div className="panel-content">{children}</div>  </div>  ); }; // Usage <CollapsiblePanel id="marketing" title="Campaign Results" clickStrategy={clickStrategies.colorSparkle} />  <CollapsiblePanel id="dashboard" title="Web Traffic" clickStrategy={clickStrategies.disabled} /> 
Enter fullscreen mode Exit fullscreen mode

Before You If/Else

When you feel an if (type === 'special') coming on, pause. Ask: “Could this be a strategy instead?” If yes, extract a tiny function, pass it in, and keep your component calm. Future-you (and your team) will thank you when requirements change again next sprint.

Gotchas

No default strategy? Give your component a safe fallback (e.g., disabled behavior) so it never crashes when someone forgets to pass one in.

Testing panic? Don’t test every combo :)

Over-strategizing? Not every if deserves a strategy. A quick inline check is fine when there are only one or two cases and they won’t grow - extract them when you actually need the third variation.

When NOT to use Strategy:

  • Simple toggles (theme.dark ? 'dark' : 'light')
  • One-off customizations that won't grow
  • Performance-critical paths (strategy dispatch has overhead)

When Strategy shines:

  • Multiple implementations of the same interface
  • Runtime behavior switching
  • Plugin architectures
  • Algorithm families that need to be swappable

Final Thoughts

Strategy is the gateway drug to plugin architectures. Mastering this helps you build micro-frontends, extensible design systems, and even frameworks that don't lock you into their opinions. Your components become platforms, not just UI blocks.

Posting in case it helps someone.

Top comments (0)