设计模式之装饰模式

1、动态地给一个对象添加一些额外的职责,就增加工能来说,装饰模式比生成子类更为灵活。

Component是定义一个对象接口,可以这些对象动态添加职责。ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。

Decorator装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator存在的。至于ConcreteDecorator就是具体的装饰对象起到给Component添加职责的功能。

UML图如下:


2、装饰模式是利用SetComponent来对对象进行包装的,这样每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中。

如果只有一个ConcreteComponent类而没有抽象的Compnent类,那么Decorator类可以是ConcreteComponent的一个子类。同样道理,如果只有一个ConcreteDecorator类那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConreteDecorator的责任合并成为一个类。


3、装饰模式是为已有功能动态地添加更多功能的一种方式,当系统需要新的功能的时候,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为。

在主类中加入新的字段,新的方法和新的逻辑从而增加了主要类的复杂度,而这些新加入的东西仅仅是为了满足一些只存在某种特定情况下才会执行的特殊行为的需要。

而装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它要装饰的对象,因此,当需要执行特殊的行为时,客户代码就可以在运行时根据需要有选择地,按顺序地使用装饰功能包装对象。


4、装饰模式的优点:

把类中的装饰功能从类中搬移去除,这样就可以简化原有的类。更大的好处是有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。有一点要注意就是装饰模式的装饰顺序很重要,比如加密数据和过滤词汇都可以是数据持久化前的装饰功能,但若是先加密了数据再过滤功能就会出问题了。最理想的情况,是保证装饰类之间的彼此独立,这样它们就可以以任何的顺序进行结合了。


 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream>
#include <string>
using  namespace std;

//抽象组件类,定义了接口
class Component
{
public:
     virtual  void Operation() =  0;
};

//具体组件类
class ConcreteComponent:  public Component
{
public:
     void Operation()
    {
        cout <<  "具体对象的操作" << endl;
    }
};

//装饰类,从这里开始了对象链。
class Decorator:  public Component
{
protected:
    Component *p_component;
public:
    Decorator()
    {
        p_component =  NULL;
    }
     void SetComponent(Component *p_component)
    {
        Decorator::p_component = p_component;
    }
     void Operation()
    {
         if (p_component !=  NULL)
        {
            p_component->Operation();
        }
    }
};

//具体装饰类A
class ConcreteDecoratorA :  public Decorator
{
private:
    string addState;
public:
     void Operation()
    {
        Decorator::Operation();
        addState =  "New State";
        cout <<  "具体装饰对象A的操作" << endl;
    }
};

//具体装饰类B
class ConcreteDecoratorB :  public Decorator
{
private:
     void AddBehavior()
    {
        cout <<  "added behavior" << endl;
    }
public:
     void Operation()
    {
        Decorator::Operation();
        AddBehavior();
        cout <<  "具体装饰对象B的操作" << endl;
    }
};

int main()
{
    ConcreteComponent c;
    ConcreteDecoratorA a;
    ConcreteDecoratorB b;
    a.SetComponent(&c);
    b.SetComponent(&a);
    b.Operation();
     return  0;
}




有时我们希望给某个对象而不是整个类添加一些功能。比如有一个手机,允许你为手机添加特性,比如增加挂件、屏幕贴膜等。一种灵活的设计方式是,将手机嵌入到另一对象中,由这个对象完成特性的添加,我们称这个嵌入的对象为装饰。这个装饰与它所装饰的组件接口一致,因此它对使用该组件的客户透明。

下面给出装饰模式的UML图。


在这种设计中,手机的装饰功能被独立出来,可以单独发展,进而简化了具体手机类的设计。

下面给出Phone类的实现:

[cpp]  view plain copy
  1. //公共抽象类  
  2. class Phone  
  3. {  
  4. public:  
  5.     Phone() {}  
  6.     virtual ~Phone() {}  
  7.     virtual void ShowDecorate() {}  
  8. };  

        具体的手机类的定义:

[cpp]  view plain copy
  1. //具体的手机类  
  2. class iPhone : public Phone  
  3. {  
  4. private:  
  5.     string m_name; //手机名称  
  6. public:  
  7.     iPhone(string name): m_name(name){}  
  8.     ~iPhone() {}  
  9.     void ShowDecorate() { cout<<m_name<<"的装饰"<<endl;}  
  10. };  
  11. //具体的手机类  
  12. class NokiaPhone : public Phone  
  13. {  
  14. private:  
  15.     string m_name;  
  16. public:  
  17.     NokiaPhone(string name): m_name(name){}  
  18.     ~NokiaPhone() {}  
  19.     void ShowDecorate() { cout<<m_name<<"的装饰"<<endl;}  
  20. };  

        装饰类的实现:

[cpp]  view plain copy
  1. //装饰类  
  2. class DecoratorPhone : public Phone  
  3. {  
  4. private:  
  5.     Phone *m_phone;  //要装饰的手机  
  6. public:  
  7.     DecoratorPhone(Phone *phone): m_phone(phone) {}  
  8.     virtual void ShowDecorate() { m_phone->ShowDecorate(); }  
  9. };  
  10. //具体的装饰类  
  11. class DecoratorPhoneA : public DecoratorPhone  
  12. {  
  13. public:  
  14.     DecoratorPhoneA(Phone *phone) : DecoratorPhone(phone) {}  
  15.     void ShowDecorate() { DecoratorPhone::ShowDecorate(); AddDecorate(); }  
  16. private:  
  17.     void AddDecorate() { cout<<"增加挂件"<<endl; } //增加的装饰  
  18. };  
  19. //具体的装饰类  
  20. class DecoratorPhoneB : public DecoratorPhone  
  21. {  
  22. public:  
  23.     DecoratorPhoneB(Phone *phone) : DecoratorPhone(phone) {}  
  24.     void ShowDecorate() { DecoratorPhone::ShowDecorate(); AddDecorate(); }  
  25. private:  
  26.     void AddDecorate() { cout<<"屏幕贴膜"<<endl; } //增加的装饰  
  27. };  

         客户使用方式:

[cpp]  view plain copy
  1. int main()  
  2. {  
  3.     Phone *iphone = new NokiaPhone("6300");  
  4.     Phone *dpa = new DecoratorPhoneA(iphone); //装饰,增加挂件  
  5.     Phone *dpb = new DecoratorPhoneB(dpa);    //装饰,屏幕贴膜  
  6.     dpb->ShowDecorate();  
  7.     delete dpa;  
  8.     delete dpb;  
  9.     delete iphone;  
  10.     return 0;  
  11. }  

装饰模式提供了更加灵活的向对象添加职责的方式。可以用添加和分离的方法,用装饰在运行时刻增加和删除职责。装饰模式提供了一种“即用即付”的方法来添加职责。它并不试图在一个复杂的可定制的类中支持所有可预见的特征,相反,你可以定义一个简单的类,并且用装饰类给它逐渐地添加功能。可以从简单的部件组合出复杂的功能。

[DP]在本文的例子中,我们定义了两个具体的手机类,iPhone类和NokiaPhone类,通过单独的装饰类为它们添加特性,从而组合出复杂的功能。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值