定义:
装饰器模式(Decorator):动态的给一个对象添加一些额外的职责,就增加功能来说,装饰器比生成子类更加灵活。
结构:
- Component:定义一个对象接口,可以给这些对象动态地添加职责。
- ConcreteComponent:定义了一个具体的对象,也可以给这个对象添加一些职责。
- Decorator:装饰抽象类,继承了 Component ,从外类来扩展 Component 类的功能,但对于 Component 来说,是无需知道 Decorator 的存在的。
- ConcreteDecorator:具体的装饰对象,起到给 Component 添加职责的功能。
代码实例:
这里以一个游戏角色为例,角色本身自带基础攻击属性,也可以通过额外的武器装备增加属性值。这里的装备武器就是动态的给角色添加额外的职责。
1、角色Role.php,对应Component
/**
* 角色,抽象类
* Class Role
*/
abstract class Role
{
/**
* @return mixed
*/
abstract public function getName();
/**
* @return mixed
*/
abstract public function getAggressivity();
}
2、武器Arms.php,对应ConcreteComponent
/**
* 武器,继承抽象类
* Class Arms
*/
class Arms extends Role
{
/**
* 基础攻击力
* @var int
*/
private $aggressivity = 100;
/**
* @return string
*/
public function getName()
{
// TODO: Implement getName() method.
return '基础攻击值';
}
/**
* @return int
*/
public function getAggressivity()
{
// TODO: Implement getAggressivity() method.
return $this->aggressivity;
}
}
3、装饰抽象类RoleDecorator.php,对应Decorator
/**
* 装饰抽象类
* Class RoleDecorator
*/
abstract class RoleDecorator extends Role
{
/**
* @var Role
*/
protected $role;
/**
* RoleDecorator constructor.
* @param Role $role
*/
public function __construct(Role $role)
{
$this->role = $role;
}
}
4、剑Sword.php,对应ConcreteDecorator
/**
* 剑,具体装饰对象,继承装饰抽象类
* Class Sword
*/
class Sword extends RoleDecorator
{
/**
* @return mixed|string
*/
public function getName()
{
// TODO: Implement getName() method.
return $this->role->getName() . '+斩妖剑';
}
/**
* @return int|mixed
*/
public function getAggressivity()
{
// TODO: Implement getAggressivity() method.
return $this->role->getAggressivity() + 200;
}
}
5、枪Gun.php,对应ConcreteDecorator
/**
* 枪,具体装饰对象,继承装饰抽象类
* Class Gun
*/
class Gun extends RoleDecorator
{
/**
* @return mixed|string
*/
public function getName()
{
// TODO: Implement getName() method.
return $this->role->getName() . '+震天戟';
}
/**
* @return int|mixed
*/
public function getAggressivity()
{
// TODO: Implement getAggressivity() method.
return $this->role->getAggressivity() + 150;
}
}
6、调用
// 基础攻击值
$arms = new Arms();
echo $arms->getName();
echo $arms->getAggressivity() . '<br>';
// 基础攻击值+斩妖剑
$sword = new Sword(new Arms());
echo $sword->getName();
echo $sword->getAggressivity() . '<br>';
// 基础攻击值+震天戟
$gun = new Gun(new Arms());
echo $gun->getName();
echo $gun->getAggressivity() . '<br>';
// 基础攻击值+斩妖剑+震天戟
$person = new Gun(new Sword(new Arms()));
echo $person->getName();
echo $person->getAggressivity() . '<br>';
7、结果:
基础攻击值100
基础攻击值+斩妖剑300
基础攻击值+震天戟250
基础攻击值+斩妖剑+震天戟450
总结:
- 装饰器模式就是为已有功能动态地添加更多功能地一种方式。当系统需要新功能时,这些新加入的功能仅仅是为了满足一些特定情况下才会执行的特殊行为的需要。这时,装饰器模式提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,但需要执行特殊行为时,客户端代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了。
- 装饰器模式把类中地装饰功能从类中移除,简化了原有的类。
- 有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。