The Strategy design pattern exists to allow us to alter the behavior of an object at runtime.
Let's suppose we have a class that will raise a number to a power, but at runtime we want to alter whether we square or cube a number.
Let's start off by defining an interface a function that will raise a number to a given power:
<?php interface Power { public function raise(int $number): int; }
We can accordingly define classes to Square
and also Cube
a given number by implementing the interface.
Here's our Square
class:
<?php class Square implements Power { public function raise(int $number): int { return pow($number, 2); } }
And let's define our Cube
class:
<?php class Cube implements Power { public function raise(int $number): int { return pow($number, 3); } }
We can now build a class that will essentially use one of these classes to process a number.
Here's the class:
<?php class RaiseNumber { public function __construct(Power $strategy) { $this->strategy = $strategy; } public function raise(int $number) { return $this->strategy->raise($number); } }
Now we can demonstrate this whole setup using an index.php
file:
<?php require_once('Power.php'); require_once('Square.php'); require_once('Cube.php'); require_once('RaiseNumber.php'); $processor = new RaiseNumber(new Square()); var_dump($processor->raise(5));
The output is as expected, 52 is 25
.
Here's the output:
We can swap the Square
object with the Cube
object in our index.php
file:
<?php require_once('Power.php'); require_once('Square.php'); require_once('Cube.php'); require_once('RaiseNumber.php'); $processor = new RaiseNumber(new Cube()); var_dump($processor->raise(5));
Here's the output of the updated script:
So far so good; but the reason that this is great is the fact that we can dynamically add logic that actually changes the operation of the class.
Here's a rather crude demonstration of all this:
<?php require_once('Power.php'); require_once('Square.php'); require_once('Cube.php'); require_once('RaiseNumber.php'); if (isset($_GET['n'])) { $number = $_GET['n']; } else { $number = 0; } if ($number < 5) { $power = new Cube(); } else { $power = new Square(); } $processor = new RaiseNumber($power); var_dump($processor->raise($number));
So just to demonstrate this, let's run the script with the nGET
variable set to 4
, which should cube the number 4
, giving an output of 64
:
Now if we pass through the number 6
, we expect the script to square the number 6
, giving an output of 36
:
In this design pattern, we have done a lot:
Now we can vary the algorithm independently from the clients that use it.
18.224.44.53