purpose
Separate "strategies" and enable them to quickly switch to each other. In addition, this model is a good alternative to inheritance (alternative to the use of extended abstract classes).
example
-
Simplified version of unit testing: for example, switching between using file storage and memory storage
-
Sort a list of objects, one by date and one by id
UML graphics
Code
- Context.php
<?php
namespace DesignPatterns\Behavioral\Strategy;
class Context
{
/**
* @var ComparatorInterface
*/
private $comparator;
public function __construct(ComparatorInterface $comparator)
{
$this->comparator = $comparator;
}
public function executeStrategy(array $elements) : array
{
uasort($elements, [$this->comparator, 'compare']);
return $elements;
}
}
- ComparatorInterface.php
<?php
namespace DesignPatterns\Behavioral\Strategy;
interface ComparatorInterface
{
/**
* @param mixed $a
* @param mixed $b
*
* @return int
*/
public function compare($a, $b): int;
}
- DateComparator.php
<?php
namespace DesignPatterns\Behavioral\Strategy;
class DateComparator implements ComparatorInterface
{
/**
* @param mixed $a
* @param mixed $b
*
* @return int
*/
public function compare($a, $b): int
{
$aDate = new \DateTime($a['date']);
$bDate = new \DateTime($b['date']);
return $aDate <=> $bDate;
}
}
- IdComparator.php
<?php
namespace DesignPatterns\Behavioral\Strategy;
class IdComparator implements ComparatorInterface
{
/**
* @param mixed $a
* @param mixed $b
*
* @return int
*/
public function compare($a, $b): int
{
return $a['id'] <=> $b['id'];
}
}
test
- Tests/StrategyTest.php
<?php
namespace DesignPatterns\Behavioral\Strategy\Tests;
use DesignPatterns\Behavioral\Strategy\Context;
use DesignPatterns\Behavioral\Strategy\DateComparator;
use DesignPatterns\Behavioral\Strategy\IdComparator;
use PHPUnit\Framework\TestCase;
class StrategyTest extends TestCase
{
public function provideIntegers()
{
return [
[
[['id' => 2], ['id' => 1], ['id' => 3]],
['id' => 1],
],
[
[['id' => 3], ['id' => 2], ['id' => 1]],
['id' => 1],
],
];
}
public function provideDates()
{
return [
[
[['date' => '2014-03-03'], ['date' => '2015-03-02'], ['date' => '2013-03-01']],
['date' => '2013-03-01'],
],
[
[['date' => '2014-02-03'], ['date' => '2013-02-01'], ['date' => '2015-02-02']],
['date' => '2013-02-01'],
],
];
}
/**
* @dataProvider provideIntegers
*
* @param array $collection
* @param array $expected
*/
public function testIdComparator($collection, $expected)
{
$obj = new Context(new IdComparator());
$elements = $obj->executeStrategy($collection);
$firstElement = array_shift($elements);
$this->assertEquals($expected, $firstElement);
}
/**
* @dataProvider provideDates
*
* @param array $collection
* @param array $expected
*/
public function testDateComparator($collection, $expected)
{
$obj = new Context(new DateComparator());
$elements = $obj->executeStrategy($collection);
$firstElement = array_shift($elements);
$this->assertEquals($expected, $firstElement);
}
}
The Growth Path of PHP Internet Architect * The Ultimate Guide to "Design Patterns"
PHP Internet Architect 50K Growth Guide + Industry Problem Solving Guide (Continuous Update)
Interview with 10 companies, get 9 offers, PHP interview questions in 2020
★If you like my article and want to communicate and learn with more senior developers, get more technical consultation and guidance related to interviews with big companies, welcome to join our group, password: phpzh
The latest PHP advanced tutorial in 2020, full series!
If the content is good, I hope everyone will support and encourage you to give a like/like, and welcome to communicate together; in addition, if you have any questions, you can suggest what you want to see in the comments.