Archive for the 'Strategy' Category

Page 2 of 2

Bedrock Strategy Pattern: The Family of Algorithms

AlgorithmFamilyOrganizing Algorithms

Working through Larry Ullman’s PHP Advanced and Object-Oriented Programming (3rd Ed) book with the Boston PHP Percolator group, we came to an example of the Strategy pattern, and I decided to re-write it. I was able to preserve Larry’s sort algorithms, but I took a different tact for the rest of the pattern. One of my favorite features of the Strategy pattern is that the Gang of Four note that it removes the need for conditional statements. Oh boy! No conditional statements!

You may well wonder why not having conditional statements is a good thing. Simple. Without conditional statements in a program, it’s easier to update and change it. If you’ve ever written a big program and you make changes, you have to go through all of the conditional statements and make sure that needed changes have not upset the coding apple cart. (The State design pattern is another one that has no conditional statements.) This does not mean that design patterns are anti-conditonal statements, but they can get in the way when making changes and updates. Besides, only the Strategy and State patterns are mentioned as having the advantage of no conditional statements. The client makes a request, and the pattern goes straight to requested property or operation with no if’s or switches. After all, if a client wants an algorithm, why should it have to go through a conditional series if it knows what it wants? (If the client is not sure what it needs, a Chain of Responsibility pattern, that does have conditional statements, is used. However, all the conditionals are pretty much the same and just check to see if the request has to be passed along the chain.) To get started take a look at the generated output and download the files:
PlayDownload

Context class and Strategy interface

Larry Ullman’s idea of using different sort algorithms is a perfect example of a “family of algorithms.” So when creating this particular Strategy pattern, I kept the same algorithms, but I removed the conditionals from the concrete strategies. To get started you can take a look at the formal class diagram in the first PHP Strategy pattern placed on this blog. After taking a look at it, consider Figure 1 that shows the general files used and their relationship to one another:

Figure 1: File Diagram of Strategy Pattern

Figure 1: File Diagram of Strategy Pattern

We begin with the Context class. It has three features (GoF 317):

  1. It is configured with a ConcreteStrategy object.
  2. It maintains a reference to a Strategy object.
  3. It may define an interface that lets Strategy access its data.

First, look at the following Context class. The first thing to note is that it is not an abstract class nor an interface. See if you can recognize the three elements the the Context participant listed above:

< ?php
class Context 
{
    private $strategy;
 
    public function __construct(IStrategy $strategy) 
        {
        $this->strategy = $strategy;
    }
 
    public function algorithm(Array $elements) 
        {
        $this->strategy->algorithm($elements);
    }
}
?>

You can see that the constructor function calls for a ConcreteStrategy. We know that because the type hinting shows that the data type must be IStrategy. Looking ahead, you find that IStrategy is an interface; not a concrete class so you may think, “That’s wrong!” However, PHP type hinting allows the data type to be a child of the named type. (The same is true for strongly typed languages like C# and Java as well.) Further, a principle of design patterns is to program to the interface and not the implementation. Besides, you cannot create an instance of an interface or abstract class anyway, so the type would have to be a concrete implementation of the interface (IStrategy, which is the Strategy participant in this example).

Second, it maintains a reference to the Strategy object (IStrategy in the example). The private variable $strategy is assigned a Strategy instance. Again we know that because the type hinting requires an IStrategy type.

Third, the class defines an interface that gives Strategy access to its data in the algorithm() method. Note that the $strategy property is part of algorithm() method that has been instantiated through the IStrategy type hinted argument passed in constructor.

The Strategy participant in the design pattern is an interface, IStrategy. It is nothing more than a method expecting an array as an argument. The individual concrete strategy classes instantiate the method in any way they want, as long as the argument is an array.

< ?php
interface IStrategy 
{
    public function algorithm(Array $elements);
}
?>

Think of the algorithm() method as a way for the Strategy to access the data.
Continue reading ‘Bedrock Strategy Pattern: The Family of Algorithms’

PHP Strategy Design Pattern: Encapsulating Algorithms

Strategy Design PatternOne of the most useful design patterns is the Strategy pattern. Where variation in algorithm use is key, the Strategy pattern encapsulates the algorithms and uses delegation to handle requests. You can easily change algorithms by re-writing the code just for the algorithm. Adding algorithms is just as easy when the requirements for your application change because all of the code for the algorithm is encapsulated in separate objects (classes). So instead of having your algorithms scattered all over the place, the Strategy pattern organizes and encapsulates them.

To get started, take a look at the class diagram for the Strategy pattern. If you are familiar with the State design pattern, you’ll see that the class diagrams are identical, but do not assume that the patterns are the same because they are very different. When we discuss the State pattern, we’ll look at those differences, but for now, just focus on the Strategy pattern itself.

Figure 1: Strategy class diagram

All requests from the Client (not shown in the diagram) go through the Context class to the Concrete Strategies through the Strategy interface.

Before continuing you need to know that not only do design patterns use a lot of classes, but they are typically saved in separate files. When it comes time to update and re-use materials, this arrangement works quite well. Further, you have to place all of the files in the same directory—this was done to keep it simple, but feel free to change that into multiple directories and re-code the materials so that the links are updated. Save some time by downloading all the code and get an idea of what the program does by clicking on the appropriate button below:

Algorithm Writers’ Heaven

I’ve never met two PHP programmers who agree on the same algorithm for…well just about anything. This is the beauty of the Strategy design pattern. All of the algorithms are encapsulated, and so if you don’t like the algorithms, you can change them to suit your own style and wisdom. Further, if you decide to add functionality to a program or to change the functionality, you can simply change one of the algorithms without the whole house come crashing down around your ears. Of course the Strategy pattern was not designed for cantankerous PHP programmers who don’t like other’s algorithms but rather for programmers who have to deal with changing functionality in an application or several different algorithms from the same “family.” In effect, you set up an interchangeable set of algorithms by establishing an interface with the desired method(s) and control the whole operation through a context class.

The algorithms can vary independent of the client (Client class) who uses it. Further, the strategies eliminate the need for conditional statement. Instead of using a conditional to call a different algorithm, the strategies are encapsulated in separate classes (implementations of a strategy interface), and so they can be called directly by the client through the context.

What’s Wrong with Conditional Statements?

Let me just blurt it out :

I avoid conditional statements whenever possible.

Such a claim may seem to be a little odd since the Chain of Responsibility pattern uses them extensively. The handleRequest() method in all of the concrete Handler classes use conditional statements. That’s true, but the conditionals are all the same and only check to see whether the request can be handled by the current concrete handler or not. These operations are little checkers or inspectors that either handle to request or pass it along the chain. They’re not the kind that have to think about several alternatives.
Continue reading ‘PHP Strategy Design Pattern: Encapsulating Algorithms’