设计模式-1.11装饰模式
装饰模式:
Decorate,动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。(DP)
装饰模式提供了更加灵活的向对象添加职责的方式。可以用添加和分离的方法,用装饰在运行时刻增加和删除职责。装饰模式提供了一种“即用即付”的方法来添加职责。它并不试图在一个复杂的可定制的类中支持所有可预见的特征,相反,你可以定义一个简单的类,并且用装饰类给它逐渐地添加功能。可以从简单的部件组合出复杂的功能。
实例:
比如有一个手机,允许你为手机添加特性,比如增加挂件、屏幕贴膜等。一种灵活的设计方式是,将手机嵌入到另一对象中,由这个对象完成特性的添加,我们称这个嵌入的对象为装饰。这个装饰与它所装饰的组件接口一致,因此它对使用该组件的客户透明。下面给出装饰模式的UML图。
在这种设计中,手机的装饰功能被独立出来,可以单独发展,进而简化了具体手机类的设计。下面给出Phone类的实现:
1 //公共抽象类 2 class Phone 3 { 4 public: 5 Phone() {} 6 virtual ~Phone() {} 7 virtual void ShowDecorate() {} 8 }; 9 10 //具体的手机类 11 class iPhone : public Phone 12 { 13 private: 14 char * m_name; //手机名称 15 public: 16 iPhone(char* name): m_name(name){} 17 ~iPhone() {} 18 void ShowDecorate() 19 { 20 cout<<m_name<<"的装饰"<<endl; 21 } 22 }; 23 24 //具体的手机类 25 class NokiaPhone : public Phone 26 { 27 private: 28 char* m_name; 29 public: 30 NokiaPhone(char* name): m_name(name){} 31 ~NokiaPhone() {} 32 void ShowDecorate() 33 { 34 cout<<m_name<<"的装饰"<<endl; 35 } 36 };
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() 9 { 10 m_phone->ShowDecorate(); 11 } 12 }; 13 14 //具体的装饰类 15 class DecoratorPhoneA : public DecoratorPhone 16 { 17 public: 18 DecoratorPhoneA(Phone *phone) : DecoratorPhone(phone) {} 19 //此处体现了顺序,可以在这里修改顺序,AddDecorate(); DecoratorPhone::ShowDecorate(); 20 void ShowDecorate() 21 { 22 DecoratorPhone::ShowDecorate(); 23 AddDecorate(); 24 } 25 26 private: 27 void AddDecorate() { cout<<"增加挂件"<<endl; } //增加的装饰 28 }; 29 30 //具体的装饰类 31 class DecoratorPhoneB : public DecoratorPhone 32 { 33 public: 34 DecoratorPhoneB(Phone *phone) : DecoratorPhone(phone) {} 35 //此处体现了顺序,可以在这里修改顺序,AddDecorate(); DecoratorPhone 36 void ShowDecorate() 37 { 38 DecoratorPhone::ShowDecorate(); 39 AddDecorate(); 40 } 41 42 private: 43 void AddDecorate() { cout<<"屏幕贴膜"<<endl; } //增加的装饰 44 };
1 // 装饰模式.cpp : Defines the entry point for the console application. 2 // 3 4 #include "stdafx.h" 5 #include <STDIO.H> 6 #include <STRING.H> 7 #include <IOSTREAM> 8 using namespace std; 9 int main(int argc, char* argv[]) 10 { 11 Phone *phone = new iPhone("IPhone");//使用指针类型,形参不会成才新的实例对象 12 DecoratorPhone *dpa = new DecoratorPhoneA(phone);//体现选择性,选择需要的装饰 13 DecoratorPhone *dpb = new DecoratorPhoneB(dpa);//选择需要的装饰 14 phone->ShowDecorate(); 15 //IPhone的装饰 16 cout<<endl; 17 dpa->ShowDecorate(); 18 //IPhone的装饰 19 //增加挂件 20 cout<<endl; 21 dpb->ShowDecorate(); 22 //IPhone的装饰 23 //增加挂件 24 //屏幕贴膜 25 return 0; 26 }
使用场景:
当系统需要新功能的时候,是想旧的类中添加新的代码,这些新加的代码通常装饰了原有类的核心职责或主要行为,这种做法的问题在于,在主类中加入了新的字段、新的方法和新的逻辑,从而增加了主类的复杂度,而这些新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要。而装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象。
优点:
把类中的装饰功能从类中搬移去除,有效地把类的核心职责和装饰功能区分开来,而且可以去除相关类中重复的装饰逻辑,这也可以简化原有的类。