装饰器模式
2018-01-08 本文已影响22人
wudanyang
什么是装饰器模式
给已有的对象增加装饰。在原有对象的基础上增加一些东西来创建一个新的对象,达到不改变原类文件以及不使用继承的情况下。
类图中包含一个隐含的 Client 类。
类图:
装饰器类图
为什么要使用装饰器模式
- 装饰器模式与继承都能扩展原有对象的功能,但是装饰器模式更加灵活,开发者可以随心所欲的搭配装饰器。
- 不用修改原类
此设计符合“四人帮”
提出的开闭原则和优先使用对象组合而不是类继承原则。
什么时候使用装饰器模式
引用自百度百科:
- 需要扩展一个类的功能,或给一个类添加附加职责。
- 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
- 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
- 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
怎么使用装饰器模式
- 装饰器类需要实现被装饰者的接口,这样,客户端就会以为这是一个对象。
- 装饰器需要引用被装饰对象。
show me your code
<?php
// 装饰器模式
interface Hero
{
public function equip();
}
/**
* 白起 -- 被装饰者
*/
class Zheng implements Hero
{
private $heroName = 'Zheng';
public $equipments;
public function equip()
{
$this->equipments = [];
}
public function showEquipments()
{
echo $this->heroName.' with ('.implode(',', $this->equipments).')';
}
}
/**
* 抽象装饰器
*/
abstract class Equipment implements Hero
{
public $hero;
public function __construct(Hero $hero)
{
$this->hero = $hero;
}
public function equip() {}
public function showEquipments()
{
$this->hero->showEquipments();
}
}
/**
* 具体装饰器 - 鞋子
*/
class Shoes extends Equipment
{
public function __construct(Hero $hero)
{
parent::__construct($hero);
}
public function equip()
{
$this->hero->equipments[] = 'shoes';
}
}
/**
* 具体装饰器 - 盔甲
*/
class armour extends Equipment
{
public function __construct(Hero $hero)
{
parent::__construct($hero);
}
public function equip()
{
$this->hero->equipments[] = 'armour';
}
}
/**
* client
*/
class client
{
public function run()
{
$zheng = new Zheng();
$zhengWithShoes = new Shoes($zheng);
$zhengWithShoes->equip();
$zhengWithArmour = new armour($zheng);
$zhengWithArmour->equip();
$zhengWithArmour->showEquipments();
}
}
$client = new client();
$client->run();
输出结果:
Zheng with (shoes,armour)
参考文献
[B] Learning PHP设计模式
[L] 百度百科-装饰模式
[注]: B 代表书,L 代表网络链接