装饰模式:一个类有一些核心功能;但随着业务改变,需要能够在核心功能之外加一些功能。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,提供比继承更多的灵活性。
给某个对象,而不是整个类,添加一些功能。就增加功能来说,装饰器模式比相比生成子类更加灵活。
适用性:
1、在不影响其它对象的情况下,以动态、透明的方式给单个对象添加职责。
2、处理那些可以撤销的职责。
3、希望为某个对象而不是一整个类添加一些功能时。
4、当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
装饰模式的UML图:
Component
——定义一个对象接口,可以给这些对象动态的添加职责。
ConcreteComponent
——定义一个对象,可以给这个对象添加一些职责。
Decorator
——维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。
ConcreteDecorator
——向组件添加职责。
注意:
1、接口的一致性。装饰对象的接口必须与它所装饰的Component的接口是一致的。
2、省略抽象的Docorator类。当你仅需要添加一个职责的时,没有必要定义抽象Decorator类。你常常需要处理显存的类层次结构而不是设计一个新系统,这时你可以把Decorator向Component转发请求的职责合并到ConcreteDecorator中。
3、保持Component类的简单性。为了保证接口的一致性,组件和装饰必须有一个共同的Component父类。因此保持这个类的简单些是很重要的。
具体例子:
在这种设计中,手机的装饰功能被独立出来,可以单独发展,进而简化了具体手机类的设计。下面给出Phone类的实现:
- //公共抽象类
- class Phone
- {
- public:
- Phone() {}
- virtual ~Phone() {}
- virtual void ShowDecorate() {}
- };
具体的手机类的定义:
- //具体的手机类
- class iPhone : public Phone
- {
- private:
- string m_name; //手机名称
- public:
- iPhone(string name): m_name(name){}
- ~iPhone() {}
- void ShowDecorate() { cout<<m_name<<"的装饰"<<endl;}
- };
- //具体的手机类
- class NokiaPhone : public Phone
- {
- private:
- string m_name;
- public:
- NokiaPhone(string name): m_name(name){}
- ~NokiaPhone() {}
- void ShowDecorate() { cout<<m_name<<"的装饰"<<endl;}
- };
装饰类的实现:
- //装饰类
- class DecoratorPhone : public Phone
- {
- private:
- Phone *m_phone; //要装饰的手机
- public:
- DecoratorPhone(Phone *phone): m_phone(phone) {}
- virtual void ShowDecorate() { m_phone->ShowDecorate(); }
- };
- //具体的装饰类
- class DecoratorPhoneA : public DecoratorPhone
- {
- public:
- DecoratorPhoneA(Phone *phone) : DecoratorPhone(phone) {}
- void ShowDecorate() { DecoratorPhone::ShowDecorate(); AddDecorate(); }
- private:
- void AddDecorate() { cout<<"增加挂件"<<endl; } //增加的装饰
- };
- //具体的装饰类
- class DecoratorPhoneB : public DecoratorPhone
- {
- public:
- DecoratorPhoneB(Phone *phone) : DecoratorPhone(phone) {}
- void ShowDecorate() { DecoratorPhone::ShowDecorate(); AddDecorate(); }
- private:
- void AddDecorate() { cout<<"屏幕贴膜"<<endl; } //增加的装饰
- };
客户使用方式:
- int main()
- {
- Phone *iphone = new NokiaPhone("6300");
- Phone *dpa = new DecoratorPhoneA(iphone); //装饰,增加挂件
- Phone *dpb = new DecoratorPhoneB(dpa); //装饰,屏幕贴膜
- dpb->ShowDecorate();
- delete dpa;
- delete dpb;
- delete iphone;
- return 0;
- }
法来添加职责。