Refactoring if / else if / else Using the Strategy Design Pattern

Published on
-
4 mins read
Authors
Refactoring Using the Strategy Design Pattern

Introduction

The Strategy Design Pattern is a behavioral design pattern that allows you to define a family of algorithms, encapsulate each one in a separate class, and make them interchangeable.

In simple terms, the Strategy pattern enables a program to change its behavior at runtime by switching between different algorithms or strategies.

Instead of placing all logic inside a single class filled with conditional statements, each algorithm is separated into its own class. The main object (often called the context) can then delegate its behavior to one of these strategy objects.

The Strategy pattern generally follows three main principles:

  1. Define a family of algorithms
  2. Encapsulate each algorithm in its own class
  3. Make the algorithms interchangeable

Let’s take a look at a simple example.


Example Without Strategy Pattern

Consider the following PHP code:

<?php
class Transport
{
public function chooseTransport($mode)
{
if ($mode == "CAR") {
echo "Go to the office by car";
} else if ($mode == "BUS") {
echo "Go to the office by bus";
} else {
echo "Go to the office by taxi";
}
}
}
$transport = new Transport();
$transport->chooseTransport("CAR");

At first glance, this code looks simple and perfectly fine. However, problems start to appear when the application grows.

Every time we need to add a new transportation option or modify existing logic, we must update the chooseTransport() method. This means the business logic becomes tightly coupled with conditional statements, which makes the code harder to maintain and extend.

This is exactly the kind of situation where the Strategy Design Pattern can help.


Refactoring with the Strategy Design Pattern

To improve the design, we can refactor the code by introducing an interface that represents a transport strategy.

Each transportation method will then implement that interface.

<?php
interface TransportStrategy
{
public function selectTransport();
}
class Car implements TransportStrategy
{
public function selectTransport()
{
echo "Go to the office by car";
}
}
class Bus implements TransportStrategy
{
public function selectTransport()
{
echo "Go to the office by bus";
}
}
class Taxi implements TransportStrategy
{
public function selectTransport()
{
echo "Go to the office by taxi";
}
}
class TransportContext
{
private $transportStrategy;
public function __construct(TransportStrategy $transportStrategy)
{
$this->transportStrategy = $transportStrategy;
}
public function chooseTransport()
{
$this->transportStrategy->selectTransport();
}
}
class Transport
{
public function selectTransport(TransportStrategy $transportStrategy)
{
$transportContext = new TransportContext($transportStrategy);
$transportContext->chooseTransport();
}
}
$transport = new Transport();
$transport->selectTransport(new Car());

At first glance, this might look more complicated than the previous version. And honestly, for a small example like this, it probably does feel a bit over-engineered.

But in real-world applications where business logic can grow quickly, this pattern becomes extremely valuable.

By separating each algorithm into its own class, we make the system easier to extend without modifying existing code.


Why Use the Strategy Pattern?

Using the Strategy Design Pattern provides several advantages:

1. Easier to Extend

When adding a new strategy (for example, Motorbike or Train), we only need to create a new class that implements TransportStrategy. No need to modify existing logic.

2. Flexible Refactoring

Existing strategies can be modified, replaced, or removed without affecting the rest of the system.

3. Better Testability

Each strategy can be tested independently using unit tests, which makes the codebase more reliable and maintainable.


Final Thoughts

The Strategy Design Pattern is particularly useful when your code starts to accumulate large conditional blocks such as if / else if / else or switch statements that determine behavior.

By moving each behavior into its own strategy class, you keep your code clean, scalable, and easier to maintain.

The example above is intentionally simple so the concept is easy to understand. But once applied in larger systems, the benefits become much more apparent.

Hopefully this explanation helps you better understand when and how to use the Strategy Design Pattern in your projects.

That’s all. I hope this was helpful. See you later.