一、装饰器模式的特点及优点
特点:
- 装饰器模式通过将对象包装在一个装饰器对象中,来动态地添加新的功能,而不需要修改原始对象的代码。
- 装饰器和被装饰对象之间是松耦合的,它们可以独立变化,互不影响。
- 装饰器可以按照需要进行组合,可以通过选择不同的装饰器组合来实现不同的功能。
优点:
- 可维护性高:装饰器模式避免了使用继承带来的子类数量暴增和复杂的继承关系,使系统的维护更加容易。
- 灵活性好:装饰器模式允许在运行时动态地增加和撤销功能,可以选择不同的装饰器来实现不同的功能,使系统更加灵活。
- 复用性高:装饰器模式将复杂的功能分散到每个装饰器中,一个装饰器只实现一个功能,可以给一个对象增加多个装饰器,也可以将一个装饰器用于不同的对象,提高了装饰器功能的复用性。
- 多样性:通过选择不同的装饰器组合,可以创造出不同行为和功能的组合体,而不需要修改原有对象的代码,符合开闭原则。
二、装饰器模式必须理解概念
- 目标接口(Component):定义了被装饰对象和装饰器对象的共同接口,确保它们可以互换使用。
- 具体组件(ConcreteComponent):实现了目标接口,是被装饰的原始对象。
- 装饰器(Decorator):实现了目标接口,并持有一个被装饰对象的引用。它可以在被装饰对象的行为前后添加额外的功能。
- 具体装饰器(ConcreteDecorator):具体的装饰器类,实现了装饰器接口,并在被装饰对象的行为前后添加具体的功能。
注意:装饰器模式的目标接口和具体组件可以是第三方代码,也可以是自己编写的代码。装饰器模式的目标接口定义了装饰器和具体组件之间的通用方法,而具体组件是被装饰的对象,它实现了目标接口的方法。装饰器是一个封装器,它包含与目标对象相同的一系列方法,并将请求委派给目标对象。装饰器可以在委派请求前后对其进行处理,从而改变最终结果。
三、第三方代码使用装饰模式实例
假如有个现成类Trade,里面包含Buy和Sell两个方法,通过设计模式中的装饰器模式来包装这个类如何实现呢?
首先,定义一个基础类ITrade,其中包含Buy和Sell两个方法:
这个基础类ITrade不是必须的,装饰器可以直接继承Trade类。
但会丧失一些灵活性,有很多第三方程序也是没有基础类的。
class ITrade {
public:
virtual void Buy() = 0;
virtual void Sell() = 0;
};
然后,创建一个具体的ConcreteTrade类,实现Buy和Sell方法:
class ConcreteTrade : public ITrade {
public:
void Buy() override {
// 实现买入操作
}
void Sell() override {
// 实现卖出操作
}
};
接下来,创建一个装饰器基类Decorator,它也是ITrade的子类,并包含一个指向ITrade对象的指针:
class Decorator : public ITrade {
protected:
ITrade* trade;
public:
Decorator(ITrade* trade) : trade(trade) {}
void Buy() override {
trade->Buy();
}
void Sell() override {
trade->Sell();
}
};
最后,创建具体的装饰器类,继承自Decorator,并在Buy和Sell方法中添加额外的功能:
class LoggingDecorator : public Decorator {
public:
LoggingDecorator(Trade* trade) : Decorator(trade) {}
void Buy() override {
// 添加日志记录功能
// ...
Decorator::Buy();
}
void Sell() override {
// 添加日志记录功能
// ...
Decorator::Sell();
}
};
使用装饰器模式包装Trade类的示例代码如下:
int main() {
ITrade * Itrade = new ConcreteTrade();
trade = new LoggingDecorator(trade);
trade->Buy();
trade->Sell();
delete trade;
return 0;
}