php中装饰者模式的简单使用

装饰者模式

意图

动态地给一些对象添加一些额外地指责。就增加功能来说decorator模式比生成子类更为灵活

动机

组合模式帮助我们聚合组件,而装饰模式则使用类似结构来帮助我们改变具体组件的功能。该模式同样使用组合,但组合是在代码运行时实现的。继承是共享父类特性的一种简单的办法,但可能会使你将需要改变的特性硬编码到继承体系中,这会降低系统的灵活性。将所有功能建立在集成体系上会导致系统中的类爆炸式增多,同时尝试对继承树上的不同分支做相似的修改时,代码可能产生重复。

适用

  1. 在不影响其他对象地情况下,以动态透明地方式给单个对象添加指责
  2. 处理那些可以撤销的指责
  3. 当不能采用生成子类的方式进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸式增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成类。

优缺点

优点 比静态继承更灵活;避免在层次结构高层的类有太多的特征。

缺点 decorator与Component不一样。decorator是一个透明的包装。包装后的组件与原来的组件是有区别的,不能依赖对象标志了。有许多的小对象。

示例

现在要给冰激凌有牛奶和沙冰的,现在又要给牛奶和沙冰的冰激凌加入香草,草莓等味道,这个时候我们可以先要一个牛奶冰激凌,然后选择加入的配料,在选择过程中加入配料的价格与描述。用这个装饰功能的配料在需要的时候装饰冰激凌!

                        |----------------|
                        | 饮料 「abstract |
                        |----------------|
                                 |
                            |--------|
                            |  咖啡   |
                            |--------|
                                 |
                            |--------|
                            |  加糖   |
                            |--------|
                                 |
                            |--------|
                            |   加冰  |
                            |--------| 

抽象构件角色»冰激凌抽象类:描述与价格

1
2
3
4
5
6
abstract class ICE
{
    public abstract function getDescription();

    public abstract function cost();
}

具体构件角色»牛奶冰激凌

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class MilkIce extends ICE
{
    public $description = '纯牛奶制作的冰激淋';

    public function getDescription()
    {
        return $this->description;
    }

    public function cost()
    {
        return 17;
    }
}

具体构件角色»沙冰冰激凌:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class SlushIce extends ICE
{
    public $description = '沙冰制作的冰激凌';

    public function getDescription()
    {
        return $this->description;
    }

    public function cost()
    {
        return 10;
    }
}

抽象装饰者角色 » 需要给沙冰或者牛奶冰激淋中加入调料 建立调料的抽象类

php abstract class CondimentIce extends ICE{}

具体装饰角色»加入香草的调料

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Herb extends CondimentIce
{
    public $ice;
    public $description;

    public function __construct($ice)
    {
        $this->ice         = $ice;
        $this->description = '法国香草';
    }

    public function getDescription()
    {
        return $this->ice->getDescription() . ',' . $this->description;
    }

    public function cost()
    {
        return $this->ice->cost() + 5;
    }
}

调用示例

购买一个奶油香草冰激凌

1
$ice_object = new MilkIce();

加入香草

1
2
3
$ice_object = new Herb($ice_object);
echo $ice_object->cost();
echo $ice_object->getDescription();

执行结果

22纯牛奶制作的冰激淋,法国香草