Strategy pattern
Encapsulate different related algorithms. The client that instantiate an algorithm have no knowledge of the implementation.
abstract class Animal
{
public $flyBehavior;
}
interface Fly
{
public function fly();
}
class FlyBehavior implements Fly
{
// @Override
public function fly()
{
return "It flies";
}
}
class NonFlyBehavior implements Fly
{
// @Override
public function fly()
{
return "Can't fly";
}
}
class Dog extends Animal
{
public function __construct()
{
// This is call 'composition'
// Instead of inheritance ...
// the class is composed with different objects
$this->flyBehavior = new NonFlyBehavior(); // Look Here
}
}
class Bird extends Animal
{
public function __construct()
{
$this->flyBehavior = new FlyBehavior();
}
}
$dog = new Dog();
echo "Dog: " . $dog->flyBehavior->fly(); // Dog: Can't fly
$bird = new Bird();
echo "Bird: " . $bird->flyBehavior->fly(); // Bird: It flies
Runtime
Another great thing about composition: It allows you to change capabilities of objects at runtime.
// the dog got wings
$dog->flyBehavior = new FlyBehavior();
echo "Dog: " . $dog->flyBehavior->fly(); // Dog: It flies !
Wrong Approach
The goal is to give to Bird (and other animals) the capability to fly. Wrong approach is to add a method in the superclass. This is bad when it isn't needed in every subclass.
abstract class Animal
{
abstract function fly();
}
class Dog extends Animal
{
// @Override
public function fly() {
}
}
class Bird extends Animal
{
// @Override
public function fly() {
echo "Bird: I'm flying";
}
}
$bird = new Bird();
$bird->fly(); // Bird: I'm flying
Why don't just add method fly() only in Bird class?
Lots of duplicate code and we'll have many animals able to fly.
abstract class Animal {}
class Dog extends Animal {}
class Bird extends Animal
{
public function fly() {
echo "Bird: I'm flying";
}
}
$bird = new Bird();
$bird->fly(); // Bird: I'm flying
Interface
An interface would also generate duplicate code. Also, a superclass change shouldn't break code in subclass and viceversa.
abstract class Animal {}
interface Fly
{
public function fly();
}
class Dog extends Animal {}
class Bird extends Animal implements Fly
{
// @Override
public function fly() {
echo "Bird: I'm flying";
}
}
class Airplain extends Animal implements Fly
{
// @Override
public function fly() {
echo "Airplain: I'm flying";
}
}
$a = new Bird();
$a->fly(); // Bird: I'm flying
$b = new Airplain();
$b->fly(); // Airplain: I'm flying
Last update: 359 days ago