3.10. Strategy¶
3.10.1. Terminology:¶
- Context
- Strategy
- Concrete Strategy
3.10.2. Purpose¶
To separate strategies and to enable fast switching between them. Also this pattern is a good alternative to inheritance (instead of having an abstract class that is extended).
3.10.3. Examples¶
- sorting a list of objects, one strategy by date, the other by id
- simplify unit testing: e.g. switching between file and in-memory storage
3.10.4. UML Diagram¶
3.10.5. Code¶
You can also find these code on GitHub
ObjectCollection.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | <?php
namespace DesignPatterns\Behavioral\Strategy;
/**
* Class ObjectCollection
*/
class ObjectCollection
{
/**
* @var array
*/
private $elements;
/**
* @var ComparatorInterface
*/
private $comparator;
/**
* @param array $elements
*/
public function __construct(array $elements = array())
{
$this->elements = $elements;
}
/**
* @return array
*/
public function sort()
{
if (!$this->comparator) {
throw new \LogicException("Comparator is not set");
}
$callback = array($this->comparator, 'compare');
uasort($this->elements, $callback);
return $this->elements;
}
/**
* @param ComparatorInterface $comparator
*
* @return void
*/
public function setComparator(ComparatorInterface $comparator)
{
$this->comparator = $comparator;
}
}
|
ComparatorInterface.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?php
namespace DesignPatterns\Behavioral\Strategy;
/**
* Class ComparatorInterface
*/
interface ComparatorInterface
{
/**
* @param mixed $a
* @param mixed $b
*
* @return bool
*/
public function compare($a, $b);
}
|
DateComparator.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <?php
namespace DesignPatterns\Behavioral\Strategy;
/**
* Class DateComparator
*/
class DateComparator implements ComparatorInterface
{
/**
* {@inheritdoc}
*/
public function compare($a, $b)
{
$aDate = new \DateTime($a['date']);
$bDate = new \DateTime($b['date']);
if ($aDate == $bDate) {
return 0;
} else {
return $aDate < $bDate ? -1 : 1;
}
}
}
|
IdComparator.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <?php
namespace DesignPatterns\Behavioral\Strategy;
/**
* Class IdComparator
*/
class IdComparator implements ComparatorInterface
{
/**
* {@inheritdoc}
*/
public function compare($a, $b)
{
if ($a['id'] == $b['id']) {
return 0;
} else {
return $a['id'] < $b['id'] ? -1 : 1;
}
}
}
|
3.10.6. Test¶
Tests/StrategyTest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | <?php
namespace DesignPatterns\Behavioral\Strategy\Tests;
use DesignPatterns\Behavioral\Strategy\DateComparator;
use DesignPatterns\Behavioral\Strategy\IdComparator;
use DesignPatterns\Behavioral\Strategy\ObjectCollection;
use DesignPatterns\Behavioral\Strategy\Strategy;
/**
* Tests for Strategy pattern
*/
class StrategyTest extends \PHPUnit_Framework_TestCase
{
public function getIdCollection()
{
return array(
array(
array(array('id' => 2), array('id' => 1), array('id' => 3)),
array('id' => 1)
),
array(
array(array('id' => 3), array('id' => 2), array('id' => 1)),
array('id' => 1)
),
);
}
public function getDateCollection()
{
return array(
array(
array(array('date' => '2014-03-03'), array('date' => '2015-03-02'), array('date' => '2013-03-01')),
array('date' => '2013-03-01')
),
array(
array(array('date' => '2014-02-03'), array('date' => '2013-02-01'), array('date' => '2015-02-02')),
array('date' => '2013-02-01')
),
);
}
/**
* @dataProvider getIdCollection
*/
public function testIdComparator($collection, $expected)
{
$obj = new ObjectCollection($collection);
$obj->setComparator(new IdComparator());
$elements = $obj->sort();
$firstElement = array_shift($elements);
$this->assertEquals($expected, $firstElement);
}
/**
* @dataProvider getDateCollection
*/
public function testDateComparator($collection, $expected)
{
$obj = new ObjectCollection($collection);
$obj->setComparator(new DateComparator());
$elements = $obj->sort();
$firstElement = array_shift($elements);
$this->assertEquals($expected, $firstElement);
}
}
|