Strategy Design Pattern Using PHP

The Strategy design pattern is a behavioral design pattern that allows you to define a family of algorithms, encapsulate each one, and make them interchangeable. This pattern lets the algorithm vary independently from the clients that use it.

The Strategy Design Pattern enables the selection of an algorithm or behavior at runtime. In the Strategy pattern, we break a class that does something specific in a lot of different ways into separate classes called strategies. Instead of implementing a single algorithm directly, code receives run-time instructions as to which in a family of algorithms to use. It allows the algorithms to vary independently from clients that use them.

The pattern consists of the following components:

  1. Context: The context defines the interface of interest to clients. It delegates the work to a Strategy object.
    • It must have a field for storing a reference to one of the strategies. The context delegates the work to a linked strategy object instead of executing it on its own using multiple conditional statements.
    • The context doesn’t know the concrete class of strategy. It should work with all strategies via the strategy interface using a single trigger method. This helps in encapsulation and you can later on add more algorithms (strategies) without altering the current code.
  2. Strategy: The interface that defines the behavior or algorithm that needs to be implemented. All concrete strategies implement this interface. The strategy interface declares methods common to all supported versions of some algorithm. The context uses this interface to call the algorithm defined by concrete strategies.
  3. Concrete Strategies: The classes that implement the Strategy interface. They provide the actual implementation of the algorithm or behavior. We implement the specific algorithms here.

An Example Problem and Solution

Suppose you own a courier company and depending upon the constraints such as a number of parcels you decide on the transportation type to be used between a Motorcycle, Van and a Truck .

Each transportation type would have its own cost and path to be used.

Using a single class for all the algorithms and separating them using conditionals like If else may seem appropriate for now but later on if we have to add more similar algorithms then it may lead to too much code in a single class and may also break the current working functionality as all the code is to be managed from a single class. This may lead to scalability issue in the future and may bring up bugs in the current working code.

So here, we can make use of the Strategy Design pattern and can extract different algorithms into separate concrete classes.

In PHP, you can implement the Strategy pattern as follows:

  1. Create an interface or abstract class that defines the methods that will be used by the various strategies.
interface TransportAlgorithm {
  public function transport(array $data): array;
}

2. Create concrete classes that implement the interface or extend the abstract class, representing the different transporting algorithms that can be used.

class BikeTransport implements TransportAlgorithm {
  public function transport(array $data): array {
// implementation of cost and route analysis using Bike as a Transport       return $transportationData;
  }
}
class VanTransport implements TransportAlgorithm {
  public function transport(array $data): array {
    // implementation of cost and route analysis using Van as a Transport
    return $transportationData;
  }
}
class TruckTransport implements TransportAlgorithm {
  public function transport(array $data): array {
    // implementation of cost and route analysis using Truck as a Transport
    return $transportationData;
  }
}

3. Create a context class that will use the selected algorithm to perform the required action. This class should have a reference to the interface or abstract class.

class Transportation {
  private $transportAlgorithm;

  public function __construct(TransportAlgorithm $transportAlgorithm) {
    $this->transportAlgorithm = $transportAlgorithm;
  }

  public function courierTransport(array $data): array {
    return $this->transportAlgorithm->transport($data );
  }
}

4 . Use the context class to perform the action, passing the desired algorithm object as a parameter.

$data[numer_of_parcels] = 1000;
$transpotation = new Transportation(new TruckTransport());
$transportationData = $transpotation->transport($data );

In this example, the Transporter context class is instantiated with TruckTransport object, which will be used to transport the parcels. By changing the algorithm object passed to the Transportation constructor, you can easily change the transport algorithm used without modifying the Transportation class. Thus it makes the code more flexible and easier to maintain.

Pros and Cons of Strategy Design pattern

Pros:

  1. By using Startegy Pattern We can avoid using massive conditionals like switch if-else statements to decide between different variants of the same algorithm.
  2. By making use of the strategy pattern the main algorithms are abstarcted out from the main class and it lets you isolate the code, internal data, and dependencies of various algorithms from the rest of the code. As a result, This makes the code extensible and maintainable in the long run.

Cons:

  1. May end up over-complexing things if you have smaller bits of code that are easily maintainable.
  2. You may end up with more memory usage as more number of objects will be created.

Source link