装饰器模式是给对象动态的增加某些特性,比如咖啡店买咖啡,可以加坚果,加奶,加糖。设计一个咖啡类,如果每次新增一个选项都要修改这个类,就会破坏类的开放-封闭原则(对扩展开放,对修改封闭)。装饰器模式是在外部给类增加选项,避免直接修改类
下面我们通过一个简单的咖啡类来看看具体的装饰器模式
class ICoffee { //咖啡基类
public:
virtual std::string description() = 0;
virtual double cost() = 0;
};
class LatteCoffee : public ICoffee { //拿铁
public:
std::string description() {
return "this is Coffee latte ";
}
double cost() {
return 12.1;
}
};
class AmericanoCoffee : public ICoffee { //美式
public:
std::string description() {
return "this is Coffee Americano ";
}
double cost() {
return 10.0;
}
};
class IDecrator : public ICoffee { //装饰器基类
public:
protected:
std::shared_ptr<ICoffee> sp_coffee_;
};
class milk : public IDecrator { //加奶
public:
milk(const std::shared_ptr<ICoffee>& sp_coff) {
sp_coffee_ = sp_coff;
}
std::string description() {
std::string strdescription = "";
if (sp_coffee_) {
strdescription = sp_coffee_->description();
}
strdescription += " add milk ";
return strdescription;
}
double cost() {
if (!sp_coffee_) {
return 0.0;
}
return sp_coffee_->cost() + 1.2;
}
};
class sugar : public IDecrator { //加糖
public:
sugar(const std::shared_ptr<ICoffee>& sp_coff) {
sp_coffee_ = sp_coff;
}
std::string description() {
std::string strdescription = "";
if (sp_coffee_) {
strdescription = sp_coffee_->description();
}
strdescription += "add sugar. ";
return strdescription;
}
double cost() {
if (!sp_coffee_) {
return 0.0;
}
return sp_coffee_->cost() + 0.8;
}
};
int main() {
{
std::shared_ptr<LatteCoffee> sp_latte(make_shared<LatteCoffee>()); //拿铁
std::shared_ptr<sugar> sp_decrator(make_shared<sugar>(sp_latte)); //加糖
std::shared_ptr<sugar> sp_decrator1(make_shared<sugar>(sp_decrator)); //加糖
std::shared_ptr<milk> sp_decrator2(make_shared<milk>(sp_decrator1)); //加奶
if (sp_decrator2) {
std::cout << sp_decrator2->description() << "cost: " << sp_decrator2->cost() << std::endl;
}
}
return 0;
}
this is Coffee latte add sugar. add sugar. add milk cost: 14.9
优点:对于已经存在的对象,可以很方便的进行包装修改而不需要修改原来的类,可以灵活的扩展功能
缺点:会增加大量的装饰类,增加了程序的复杂度,新增一个功能不但需要实例化原本的类,还需要把类添加到装饰类中