Last active
December 17, 2015 02:59
-
-
Save Ivoz/5540156 to your computer and use it in GitHub Desktop.
Phur Strategy without needing custom Interfaces, using reflection
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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