装饰模式是为已有的类动态添加更多功能而且不改动原来的类;
主要是使用对象的关联关系替代继承;
就如现实生活中的装饰或者配料一样;
我们用吃喝举例;
有普通的原味奶茶、手抓饼、烤冷面;
还 vip 级的加布丁、加肠、加蛋;
使用继承可以很简单的实现;
但是经过前面几篇文章的洗礼;
我们应该已经有组合优于继承的意识了;
把配料独立出来;
结构
Component:原本的对象和装饰共同的接口
ConcreteComponent: 原本的对象 示例中指 手抓饼和烤冷面
Decorator: 实现接口的装饰抽象类
ConcreteDecorator:具体的装饰 示例中指 肠、蛋、辣条
示例
先定义共同的接口
Food.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 手抓饼
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 烤冷面
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
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 '
';
// 烤冷面
$kaolengmian = new Kaolengmian();
echo $kaolengmian->name();
echo $kaolengmian->price() . '元';
echo '
';
}
}
$client = new Client();
$client->run();
现在已经实现了烤冷面和手抓饼的制作;
下面开始加料;
定义配料抽象类;
Decorator.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 蛋
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 肠
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 辣条
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
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 '
';
// 烤冷面
$kaolengmian = new Kaolengmian();
echo $kaolengmian->name();
echo $kaolengmian->price() . '元';
echo '
';
// 手抓饼+蛋
$egg = new Egg($shouzhuabing);
echo $egg->name();
echo $egg->price() . '元';
echo '
';
// 手抓饼+肠
$sausage = new Sausage($kaolengmian);
echo $sausage->name();
echo $sausage->price() . '元';
echo '
';
// 烤冷面+辣条
$latiao = new Latiao($shouzhuabing);
echo $latiao->name();
echo $latiao->price() . '元';
echo '
';
}
}
$client = new Client();
$client->run();