Saturday, May 23, 2009

The strategy pattern using PHP

In the strategy pattern, algorithms are extracted from complex classes so they can be replaced easily. For example, the strategy pattern is an option if you want to change the way pages are ranked in a search engine. Think about a search engine in several parts -- one that iterates through the pages, one that ranks each page, and another that orders the results based on the rank. In a complex example, all those parts would be in the same class. Using the strategy pattern, you take the ranking portion and put it into another class so you can change how pages are ranked without interfering with the rest of the search engine code.
As a simpler example, Strategy.php shows a user list class that provides a method for finding a set of users based on a plug-and-play set of strategies.

Strategy.php



<?php
interface IStrategy {
function filter($record);
}

class FindAfterStrategy implements IStrategy {
private $_name;

public function __construct($name) {
$this->_name = $name;
}

public function filter($record) {
return strcmp($this->_name, $record) <= 0;     } }  class RandomStrategy implements IStrategy {     public function filter($record) {         return rand(0, 1) >= 0.5;
}
}

class UserList {
private $_list = array();

public function __construct($names) {
if ($names != null) {
foreach($names as $name) {
$this->_list []= $name;
}
}
}

public function add($name) {
$this->_list []= $name;
}

public function find($filter) {
$recs = array();
foreach($this->_list as $user) {
if ($filter->filter($user))
$recs []= $user;
}
return $recs;
}
}

$ul = new UserList(array("Andy", "Jack", "Lori", "Megan"));
$f1 = $ul->find( new FindAfterStrategy("J") );
print_r($f1);

$f2 = $ul->find(new RandomStrategy());
print_r($f2);
?>


The user list and the strategies for selecting users
The user list and the strategies for selecting users


The UserList class is a wrapper around an array of names. It implements a find method that takes one of several strategies for selecting a subset of those names. Those strategies are defined by the IStrategy interface, which has two implementations: One chooses users randomly and the other chooses all the names after a specified name. When you run the test code, you get the following output:


% php strategy.php
Array
(
[0] => Jack
[1] => Lori
[2] => Megan
)
Array
(
[0] => Andy
[1] => Megan
)
%


The test code runs the same user lists against two strategies and shows the results. In the first case, the strategy looks for any name that sorts after J, so you get Jack, Lori, and Megan. The second strategy picks names randomly and yields different results every time. In this case, the results are Andy and Megan.
The strategy pattern is great for complex data-management systems or data-processing systems that need a lot of flexibility in how data is filtered, searched, or processed.
source: ibm.com

Design Patterns for PHP

2 comments:

MichaƂ Mech said...

There are also ready to use Observer interface in SPL.
http://www.php.net/~helly/php/ext/spl/interfaceSplObserver.html

Kells said...

This pattern can also be very useful in the context of form validation.

Post a Comment