一、概述
1、装饰者模式:可以在不改变一个对象本身功能的基础上给对象增加额外的新行为
2、是一种用于替代继承的技术,它通过一种无须定义子类的方式给对象动态增加职责,使用对象之间的关联关系取代类之间的继承关系
3、引入装饰类,在装饰类中既可以调用待装饰的原有的方法,还可以增加新的方法,以扩展原有类的功能
4、定义:动态地给一个对象增加一些额外的职责,就扩展功能而言,装饰模式提供了一种比使用子类更加灵活的替代方案
二、装饰模式结构
装饰模式包含以下4个角色:
1、Component(抽象构架)
2、ConcreteComponent(具体构件类)
3、Decorator(抽象装饰类)
4、ConcreteDecorator(具体装饰类)
三、UML图
四、模式优点
1、对于扩展一个对象的功能,装饰模式比继承更加灵活,允许在运行时动态地增加、移除或组合不同的功能
2、符合单一职责原则,通过不同功能分散到不同的装饰者类中,每个装饰者类只负责一种功能,从而保持代码的清晰和模块化
3、避免类爆炸,与继承创建大量子类不同,装饰者模式通过组合装饰者实现功能扩展,从而减少了类的数量,降低了类的复杂性
五、模式缺点
1、使用装饰模式进行系统设计时将产生很多小对象,大量小对象的产生势必会占用更多的系统资源,在一定程度上影响程序的性能
2、使用装饰模式导致系统中出现大量的装饰者类,尤其是当有很多功能组合时,这可能会增加类的数量和复杂性
六、示例代码
#include <iostream>
using namespace std;
//抽象构件
class Beverge
{
public:
virtual string getDescription() = 0;
virtual double getCost() = 0;
};
//具体构件 混合咖啡类
class HouseBlend : public Beverge
{
public:
string getDescription() override
{
return "混合咖啡";
}
double getCost() override
{
return 25.00;
}
};
//具体构件 浓缩咖啡类
class Espresso : public Beverge
{
public:
string getDescription() override
{
return "浓缩咖啡";
}
double getCost()
{
return 20.00;
}
};
//抽象装饰者类 所有配料的抽象父亲
class Decorator : public Beverge
{
public:
Decorator(Beverge *beverge) : m_beverge(beverge) {}
string getDescription()
{
return m_beverge->getDescription();
}
double getCost()
{
return m_beverge->getCost();
}
private:
Beverge* m_beverge = nullptr;
};
//具体的装饰器类, 具体的配料--牛奶
class Milk : public Decorator
{
public:
Milk(Beverge *beverge) : Decorator(beverge) {}
string getDescription()
{
string decription = Decorator::getDescription();
return decription + "牛奶";
}
double getCost()
{
double cost = Decorator::getCost();
return cost + 2.0;
}
};
class Mocha : public Decorator
{
public:
Mocha(Beverge *beverge) : Decorator(beverge) {}
string getDescription()
{
string description = Decorator::getDescription();
return description + "摩卡";
}
double getCost()
{
double cost = Decorator::getCost();
return cost + 3.0;
}
};
int main()
{
string description;
double cost;
Beverge* beverge = nullptr;
beverge = new Espresso;
description = beverge->getDescription();
cost = beverge->getCost();
cout << "coffe:" << description;
cout << " 价格:" << cost;
cout << endl << "---------------------" << endl;
Beverge* beverge_mo = nullptr;
beverge_mo = new Mocha(beverge);
description = beverge_mo->getDescription();
cost = beverge_mo->getCost();
cout << "coffe:" << description;
cout << " 价格:" << cost;
cout << endl << "---------------------" << endl;
Beverge* beverge_mi = nullptr;
beverge_mi = new Milk(beverge_mo);
description = beverge_mi->getDescription();
cost = beverge_mi->getCost();
cout << "coffe:" << description;
cout << " 价格:" << cost;
cout << endl << "---------------------" << endl;
return 0;
}