⭐ 装饰者模式动态地将责任附加到对象上。 |
- 若要扩展功能,装饰者模式提供了比继承更有弹性的替代方案。
- 适用场景:需要动态的给现有对象添加功能,并且能够实现不同功能的组合。
举2个例子来理解:
咖啡,不同的咖啡加不同的配料,例如玛奇朵+双倍焦糖+奶盖,摩卡+奶盖
游戏角色,不同的游戏人物服装、使用武器不同,战士+盔甲+刀剑,法师+长袍+法杖
如果通过单纯的类继承来实现的话,将会有咖啡类、玛奇朵+双倍焦糖+奶盖的咖啡类、摩卡+奶盖的咖啡类。未来再有别的搭配的话,又要实现一个新的咖啡类,将会带来数量庞大的一堆子类,不易组合且代码量大。
装饰模式的实现
1、需要有被修饰的对象基类A、被修饰的对象派生类A-Child
2、被修饰的对象的一个方法A-Func
3、装饰基类D,从被修饰的对象基类A派生,缓存一个被修饰的对象基类对象(A *a),添加扩展方法D-Func,实现2中的方法并在其中调用D-Func
4、从装饰基类派生各种装饰类D-Child
5、使用时先生成一个被装饰对象A-Child,指向基类指针A*,然后你想给他添加什么扩展功能,就再实例化一个D-Child传入A*即可
代码如下
class Coffee { public: Coffee() { //std::cout << "Coffee construction!" << endl; } virtual ~Coffee() { //std::cout << "Coffee destruction!" << endl; }
virtual void showme() = 0; };
class CMachiatto :public Coffee { public: CMachiatto() { //std::cout << "Machiatto construction!" << endl; } ~CMachiatto() { //std::cout << "Machiatto destruction!" << endl; } void showme() { std::cout << "This is Machiatto!" << endl; } };
class CMocha :public Coffee { public: CMocha() { //std::cout << "Macho construction!" << endl; } ~CMocha() { //std::cout << "Macho destruction!" << endl; } void showme() { std::cout << "This is Macho!" << endl; } };
class Decorate :public Coffee { public: Decorate(Coffee *i_ptrCoffee) { //std::cout << "Decorate construction!" << endl; m_coffee = i_ptrCoffee; } ~Decorate() { //std::cout << "Decorate destruction!" << endl; delete m_coffee; m_coffee = NULL; }
void showme() { m_coffee->showme(); showdecorate(); } virtual void showdecorate() = 0; private: Coffee *m_coffee;
};
class CCaramel :public Decorate { public: CCaramel(Coffee *i_ptrCoffee) : Decorate(i_ptrCoffee) { //std::cout << "Caramel construction!" << endl; } ~CCaramel() { //std::cout << "Caramel destruction!" << endl; }
void showdecorate() { std::cout << "Add some caramel!" << endl; } };
class CMilk :public Decorate { public: CMilk(Coffee *i_ptrCoffee): Decorate(i_ptrCoffee) { //std::cout << "Milk construction!" << endl; } ~CMilk() { //std::cout << "Milk destruction!" << endl; }
void showdecorate() { std::cout << "Add some milk!" << endl; } };
int main() { //双焦糖+奶盖 Coffee *coff = new CMachiatto; coff = new CCaramel(coff); coff = new CCaramel(coff); coff = new CMilk(coff); coff->showme();
delete coff; coff = NULL;
//摩卡+奶盖 Coffee *newcoff = new CMocha; newcoff = new CMilk(newcoff); newcoff->showme();
delete newcoff; newcoff = NULL;
return 0; } |
运行结果如下: