php设计模式(十二)装饰模式

装饰模式是为已有的类动态添加更多功能而且不改动原来的类;
主要是使用对象的关联关系替代继承;
就如现实生活中的装饰或者配料一样;
我们用吃喝举例;
有普通的原味奶茶、手抓饼、烤冷面;
还 vip 级的加布丁、加肠、加蛋;
使用继承可以很简单的实现;

但是经过前面几篇文章的洗礼;
我们应该已经有组合优于继承的意识了;
把配料独立出来;

结构

Component:原本的对象和装饰共同的接口
ConcreteComponent: 原本的对象 示例中指 手抓饼和烤冷面
Decorator: 实现接口的装饰抽象类
ConcreteDecorator:具体的装饰 示例中指 肠、蛋、辣条

示例

先定义共同的接口
Food.php

<?php

namespace Baijunyao\DesignPatterns\Decorator;

/**
 * 食物
 *
 * Interface Food
 * @package Baijunyao\DesignPatterns\Decorator
 */
interface Food
{
    /**
     * 名称
     *
     * @return mixed
     */
    public function name();

    /**
     * 价格
     *
     * @return mixed
     */
    public function price();
}

原本的对象;
Shouzhuabing.php 手抓饼

<?php

namespace Baijunyao\DesignPatterns\Decorator;

/**
 * 手抓饼
 *
 * Class Shouzhuabing
 * @package Baijunyao\DesignPatterns\Decorator
 */
class Shouzhuabing implements Food
{
    /**
     * 名称
     *
     * @return mixed|string
     */
    public function name()
    {
        return '手抓饼';
    }

    /**
     * 价格
     *
     * @return int|mixed
     */
    public function price()
    {
        return 5;
    }
}

Kaolengmian.php 烤冷面

<?php

namespace Baijunyao\DesignPatterns\Decorator;

/**
 * 烤冷面
 *
 * Class Kaolengmian
 * @package Baijunyao\DesignPatterns\Decorator
 */
class Kaolengmian implements Food
{
    /**
     * 名称
     *
     * @return mixed|string
     */
    public function name()
    {
        return '烤冷面';
    }

    /**
     * 价格
     *
     * @return int|mixed
     */
    public function price()
    {
        return 6;
    }
}

制作烤冷面和手抓饼;
index.php

<?php

namespace Baijunyao\DesignPatterns\Decorator;

require __DIR__.'/../vendor/autoload.php';

/**
 * 客户端
 *
 * Class Client
 * @package Baijunyao\DesignPatterns\Decorator
 */
class Client
{
    /**
     *
     */
    public function run()
    {
        // 手抓饼
        $shouzhuabing = new Shouzhuabing();
        echo $shouzhuabing->name();
        echo $shouzhuabing->price() . '元';
        echo '<hr>';

        // 烤冷面
        $kaolengmian = new Kaolengmian();
        echo $kaolengmian->name();
        echo $kaolengmian->price() . '元';
        echo '<hr>';
    }
}

$client = new Client();
$client->run();

现在已经实现了烤冷面和手抓饼的制作;
下面开始加料;
定义配料抽象类;
Decorator.php

<?php

namespace Baijunyao\DesignPatterns\Decorator;

/**
 * 装饰  配料
 *
 * Class Decorator
 * @package Baijunyao\DesignPatterns\Decorator
 */
abstract class Decorator implements Food
{
    /**
     * @var Food
     */
    protected $food;

    /**
     * Decorator constructor.
     * @param Food $food
     */
    public function __construct(Food $food)
    {
        $this->food = $food;
    }
}

Egg.php 蛋

<?php

namespace Baijunyao\DesignPatterns\Decorator;

/**
 * 蛋
 *
 * Class Egg
 * @package Baijunyao\DesignPatterns\Decorator
 */
class Egg extends Decorator
{
    /**
     * 名称
     *
     * @return mixed|string
     */
    public function name()
    {
        return $this->food->name() . '+蛋';
    }

    /**
     * 价格
     *
     * @return int|mixed
     */
    public function price()
    {
        return $this->food->price() + 1;
    }
}

Sausage.php 肠

<?php

namespace Baijunyao\DesignPatterns\Decorator;

/**
 * 肠
 *
 * Class Sausage
 * @package Baijunyao\DesignPatterns\Decorator
 */
class Sausage extends Decorator
{
    /**
     * 名称
     *
     * @return mixed|string
     */
    public function name()
    {
        return $this->food->name() . '+肠';
    }

    /**
     * 价格
     *
     * @return int|mixed
     */
    public function price()
    {
        return $this->food->price() + 2;
    }
}

Latiao.php 辣条

<?php

namespace Baijunyao\DesignPatterns\Decorator;

/**
 * 辣条
 *
 * Class Latiao
 * @package Baijunyao\DesignPatterns\Decorator
 */
class Latiao extends Decorator
{
    /**
     * 名称
     *
     * @return mixed|string
     */
    public function name()
    {
        return $this->food->name() . '+辣条';
    }

    /**
     * 价格
     *
     * @return int|mixed
     */
    public function price()
    {
        return $this->food->price() + 3;
    }
}

运行;
index.php

<?php

namespace Baijunyao\DesignPatterns\Decorator;

require __DIR__.'/../vendor/autoload.php';

/**
 * 客户端
 *
 * Class Client
 * @package Baijunyao\DesignPatterns\Decorator
 */
class Client
{
    /**
     *
     */
    public function run()
    {
        // 手抓饼
        $shouzhuabing = new Shouzhuabing();
        echo $shouzhuabing->name();
        echo $shouzhuabing->price() . '元';
        echo '<hr>';

        // 烤冷面
        $kaolengmian = new Kaolengmian();
        echo $kaolengmian->name();
        echo $kaolengmian->price() . '元';
        echo '<hr>';

        // 手抓饼+蛋
        $egg = new Egg($shouzhuabing);
        echo $egg->name();
        echo $egg->price() . '元';
        echo '<hr>';

        // 手抓饼+肠
        $sausage = new Sausage($kaolengmian);
        echo $sausage->name();
        echo $sausage->price() . '元';
        echo '<hr>';

        // 烤冷面+辣条
        $latiao = new Latiao($shouzhuabing);
        echo $latiao->name();
        echo $latiao->price() . '元';
        echo '<hr>';
    }
}

$client = new Client();
$client->run();


github示例:https://github.com/baijunyao/design-patterns/tree/master/Decorator

白俊遥博客
请先登录后发表评论
  • latest comments
  • 总共4条评论
白俊遥博客

花舞千魂殇 :哇 懂了懂了

2018-12-12 08:51:19 回复

白俊遥博客

吊≈♂ :老板给我加俩蛋.

2018-10-30 15:41:27 回复

白俊遥博客

神仙 白俊遥博客

2018-10-01 08:29:25 回复

白俊遥博客

adam_liu 白俊遥博客

2018-09-25 13:33:11 回复