定義:
裝飾器模式(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
總結:
- 裝飾器模式就是爲已有功能動態地添加更多功能地一種方式。當系統需要新功能時,這些新加入的功能僅僅是爲了滿足一些特定情況下才會執行的特殊行爲的需要。這時,裝飾器模式提供了一個非常好的解決方案,它把每個要裝飾的功能放在單獨的類中,並讓這個類包裝它所要裝飾的對象,因此,但需要執行特殊行爲時,客戶端代碼就可以在運行時根據需要有選擇地、按順序地使用裝飾功能包裝對象了。
- 裝飾器模式把類中地裝飾功能從類中移除,簡化了原有的類。
- 有效地把類的核心職責和裝飾功能區分開了。而且可以去除相關類中重複的裝飾邏輯。