2016年3月13日 星期日

php composite + __call

class Weapon
{
    protected $name;

    protected $attack = 0;

    protected $addions = [];

    public function __construct($name, $attack, $addions = [])
    {
        $this->name = $name;
        $this->attack = $attack;
        $this->addions = $addions;
    }

    public function setAttack($attack)
    {
        $this->attack = $attack;
    }

    public function attack()
    {
        $attack = $this->attack;
        foreach ($this->addions as $addion) {
            $attack += $addion->attack();
        }

        return $attack;
    }

    public function __call($method, $parameters)
    {
        foreach ($this->addions as $addion) {
            if (method_exists($addion, $method) === true) {
                return call_user_func_array([$addion, $method], $parameters);
            }
        }
        die('error');
    }
}

abstract class Addion
{
    protected $attack = 0;

    public function attack()
    {
        return $this->attack;
    }
}

class ToxicAddion extends Addion
{
    protected $attack = 15;

    public function toxic()
    {
        echo 'toxic';
    }
}

class LightingAddion extends Addion
{
    protected $attack = 10;

    public function lighting()
    {
        echo 'lighting';
    }
}

$sword = new Weapon('劍', 10, [
    new ToxicAddion(),
    new LightingAddion(),
]);

echo $sword->attack();
echo $sword->toxic();
echo $sword->lighting();

// output
// 35
// toxic
// lighting

PHP decorator + __call

class Weapon
{
    public function attack()
    {
        return 10;
    }
}

abstract class Decorator
{
    protected $weapon;

    public function __construct($weapon)
    {
        $this->weapon = $weapon;
    }

    abstract public function attack();

    public function __call($method, $parameters)
    {
        return call_user_func_array([$this->weapon, $method], $parameters);
    }
}

class ToxicDecorator extends Decorator
{
    public function attack()
    {
        return $this->weapon->attack() + 15;
    }

    public function toxic()
    {
        echo 'toxic';
    }
}

class LightingDecorator extends Decorator
{
    public function attack()
    {
        return $this->weapon->attack() + 5;
    }

    public function lighting()
    {
        echo 'lighting';
    }
}

$weapon = new Weapon();
$weapon = new ToxicDecorator($weapon);
$weapon = new LightingDecorator($weapon);
echo $weapon->attack();
echo $weapon->toxic();
echo $weapon->lighting();

// output
// 30
// toxic
// lighting