Skip to content

Instantly share code, notes, and snippets.

@Ivoz
Last active December 17, 2015 02:59
Show Gist options
  • Save Ivoz/5540156 to your computer and use it in GitHub Desktop.
Save Ivoz/5540156 to your computer and use it in GitHub Desktop.
Phur Strategy without needing custom Interfaces, using reflection
<?php
/**
* @author Rick Wong <[email protected]>
* @contributor Matthew Iversen <[email protected]>
*/
namespace Phur\Strategy;
/**
* The Strategy Pattern. It is used when your application needs to
* pick one business algorithm out of many. The behavior of your
* application will be changeable at run-time, without having
* to write the same conditionals everywhere.
*
* @example (1) We can implement a Transport_Strategy that mandates the
* ITransporter interface like this:
*
* interface ITransporter
* {
* public function execute ($meters);
* }
*
* class Transport_Strategy extends \Phur\Strategy\Strategist
* {
* }
*
* class Legs implements ITransporter
* {
* public function execute ($meters) { return $meters / 1.4; } // meters per second
* }
*
* class Car implements ITransporter
* {
* public function execute ($meters) { return $meters / 30; }
* }
*
*
* @example (2) We then use the above Transport_Strategy to move around:
*
* $transport = new Transport_Strategy(new Legs);
* $walkingIsSlow = $transport->execute(100);
*
* $transport->changeStrategy(new Car);
* $carsAreFast = $transport->execute(100);
*
*/
abstract class Strategist
{
protected $_interfaces;
private $currentStrategy = null;
public function __construct($startingStrategy)
{
$reflection = new \ReflectionClass($startingStrategy);
if ($reflection->isInterface())
{
$this->_interfaces = array($reflection->getName());
}
else
{
$this->_interfaces = $reflection->getInterfaceNames();
$this->changeStrategy($startingStrategy);
}
}
public function changeStrategy($strategy)
{
$reflection = new \ReflectionClass($strategy);
foreach ($this->_interfaces as $interface)
{
if (!$reflection->implementsInterface($interface))
{
throw new \Exception($reflection->getName() . " must implement interface $interface");
}
}
$this->currentStrategy = $strategy;
}
public function __call ($action, array $context)
{
if (is_null($this->currentStrategy))
{
throw new \Exception("A strategy has not yet been chosen");
}
return call_user_func_array(array($this->currentStrategy, $action), $context);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment