装饰者模式:
允许向一个现有的对象添加新的功能,同时又不改变其结构。装饰器模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。
装饰者模式有四个角色:
1)抽象构建(Component ):给出一个抽象接口,来规范被添加职责的对象;
2)具体构件(ConcreteComponent):定义一个将要接收附加责任的具体对象;
3)装饰抽象类(Decorator):持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口;
4)具体装饰对象(ConreteDecorator):负责给构件对象 ”贴上“附加的责任。起到给Component添加职责的功能。
要点:
1)装饰者和被装饰对象有相同的超类型。
2)可以用一个或多个装饰者包装一个对象。
3)装饰者可以在所委托被装饰者的行为之前或之后,加上自己的行为,以达到特定的目的。
4)对象可以在任何时候被装饰,所以可以在运行时动态的,不限量的用你喜欢的装饰者来装饰对象。
5)装饰模式中使用继承的关键是想达到装饰者和被装饰对象的类型匹配,而不是获得其行为。
6)装饰者一般对组件的客户是透明的,除非客户程序依赖于组件的具体类型。在实际项目中可以根据需要为装饰者添加新的行为,做到“半透明”装饰者。
优点:
- 装饰这模式和继承的目的都是扩展对象的功能,但装饰者模式比继承更灵活;
- 通过使用不同的具体装饰类以及这些类的排列组合,设计师可以创造出很多不同行为的组合;
- 装饰者模式有很好地可扩展性
缺点:
装饰者模式会导致设计中出现许多小对象,如果过度使用,会让程序变的更复杂。并且更多的对象会是的差错变得困难,特别是这些对象看上去都很像。
区别:
装饰者模式与代理模式的区别:
- 两种模式的关注点不同,装饰者模式关注的是在一个对象上动态的添加方法,而代理模式关注的是控制对象的访问。
- 装饰者模式可以让使用者直观的看到增强了哪些功能,而代理模式完全限制了使用者,只去调用代理,至于代理里面增加了什么功能,使用者是不知道,隐藏了一个对象的具体信息,这正是为什么代理模式在初始化时不能像装饰模式一样传入一个原始对象的参数的原因。
- 代理和真实对象之间的的关系通常在编译时就已经确定了,而装饰者能够在运行时递归地被构造。
//公共抽象类
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(); cout<<"增加挂件"<<endl; }
//增加的装饰
};
class DecoratorPhoneB : public DecoratorPhone
{
public:
DecoratorPhoneB(Phone *phone) : DecoratorPhone(phone) {}
void ShowDecorate() { DecoratorPhone::ShowDecorate(); cout<<"屏幕贴膜"<<endl; }
};
//--------------------------------
//use
Phone *iphone = new NokiaPhone("6300");
Phone *dpa = new DecoratorPhoneA(iphone); //装饰,增加挂件
Phone *dpb = new DecoratorPhoneB(dpa); //装饰,屏幕贴膜
dpb->ShowDecorate();