【装饰模式中主要角色】
抽象构件(Component)角色:定义一个对象接口,以规范准备接收附加职责的对象,从而可以给这些对象动态地添加职责。
具体构件(Concrete Component)角色:定义一个将要接收附加职责的类。
装饰(Decorator)角色:持有一个指向Component对象的指针,并定义一个与Component接口一致的接口。
具体装饰(Concrete Decorator)角色:负责给构件对象增加附加的职责。
示例:
//抽象构建(Component)角色:Drink,饮料类
abstract class Drink {
public abstract function showDrink();
}
//具体构件(Concrete Component)角色:Coffe ,咖啡类
class Coffee extends Drink {
private $name;
public function __construct($name){
$this->name = $name;
}
public function showDrink(){
echo "咖啡的名称为:{$this->name}";
}
}
//装饰(Decorator)角色:DecoratorDrink,咖啡装饰类
abstract class DecoratorDrink extends Drink {
protected $drink;
public function __construct(Drink $drink){
$this->drink = $drink;
}
public function showDrink(){
if($this->drink != null){
$this->drink->showDrink();
}
}
}
//具体装饰(Concrete Decorator)角色:加糖类,加奶类,加热类,加冰类
class Sugar extends DecoratorDrink {
public function showDrink(){
$this->drink->showDrink();
echo " 加糖 ";
}
}
class Milk extends DecoratorDrink {
public function showDrink(){
$this->drink->showDrink();
echo " 加奶 ";
}
}
class Ice extends DecoratorDrink {
public function showDrink(){
$this->drink->showDrink();
echo " 加冰 ";
}
}
class Hot extends DecoratorDrink {
public function showDrink(){
$this->drink->showDrink();
echo " 加热 ";
}
}
调用示例:
$coffee = new Coffee("拿铁咖啡");
$sugar = new Sugar($coffee);
$hot = new Hot($sugar);
$hot->showDrink();
$blue_mountain = new Coffee("蓝山咖啡");
$milk = new Milk($blue_mountain);
$ice = new Ice($milk);
$ice->showDrink();
//输出结果为:
咖啡的名称为:拿铁咖啡 加糖 加热
咖啡的名称为:蓝山咖啡 加奶 加冰
【装饰模式的优缺点】
装饰模式的优点:
1、比静态继承更灵活;
2、避免在层次结构高层的类有太多的特征
装饰模式的缺点:
1、使用装饰模式会产生比使用继承关系更多的对象。并且这些对象看上去都很想像,从而使得查错变得困难。
【装饰模式适用场景】
1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
2、处理那些可以撤消的职责,即需要动态的给一个对象添加功能并且这些功能是可以动态的撤消的。
3、当不能彩生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。