装饰器模式 (Decorator Pattern)
意图:动态地给对象添加额外的职责,比继承更灵活。
基础组件
- Component (组件):定义对象的接口
- ConcreteComponent (具体组件):实现Component的基本功能
- Decorator (装饰器):持有Component引用,实现Component接口
- ConcreteDecorator (具体装饰器):添加具体功能
继承/实现关系
Component <|-- ConcreteComponent
Component <|-- Decorator
Decorator <|-- ConcreteDecorator
Decorator --> Component (组合)
应用场景
- 需要动态添加/撤销功能
- 不能使用子类扩展功能的情况
- 需要多种功能组合
C++ 实现(咖啡加料场景)
#include <iostream>
#include <memory>
#include <string>
/*
* 装饰器模式
* 意图:动态地给对象添加额外的职责,比继承更灵活。
* 基础组件:
* - Component (组件):定义对象的接口
* - ConcreteComponent (具体组件):实现组件接口
* - Decorator (装饰器):持有Component引用,实现Component接口
* - ConcreteDecorator (具体装饰器):扩展Decorator,添加额外的职责
* 继承/实现关系:
* ConcreteComponent 继承自 Component
* Decorator 继承自 Component,并持有 Component 的引用
* ConcreteDecorator 继承自 Decorator,并扩展其功能
*
* 值得注意的是,无论是基础组件还是装饰器,都实现了相同的接口,因此装饰器不仅可以使用在组件上,也可以为一个装饰器添加另一个装饰器,这样就可以动态地组合不同的装饰器来创建新的功能。
*/
// 组件:咖啡
class Coffee {
public:
virtual ~Coffee() = default;
virtual std::string getDescription() const = 0;
virtual double cost() const = 0;
};
// 具体组件:浓缩咖啡
class Espresso : public Coffee {
public:
std::string getDescription() const override {
return "Espresso";
}
double cost() const override {
return 1.99;
}
};
// 装饰器基类,它继承自 Coffee(保证对外的接口不变),并持有一个 Coffee 对象的引用(用来实现对外接口,实际是对Coffee具体实例的装饰)
class CoffeeDecorator : public Coffee {
public:
explicit CoffeeDecorator(std::unique_ptr<Coffee> coffee)
: coffee_(std::move(coffee)) {}
std::string getDescription() const override {
return coffee_->getDescription();
}
double cost() const override {
return coffee_->cost();
}
protected:
std::unique_ptr<Coffee> coffee_;
};
// 具体装饰器:牛奶
class Milk : public CoffeeDecorator {
public:
using CoffeeDecorator::CoffeeDecorator;
std::string getDescription() const override {
return coffee_->getDescription() + ", Milk";
}
double cost() const override {
return coffee_->cost() + 0.50;
}
};
// 具体装饰器:摩卡
class Mocha : public CoffeeDecorator {
public:
using CoffeeDecorator::CoffeeDecorator;
std::string getDescription() const override {
return coffee_->getDescription() + ", Mocha";
}
double cost() const override {
return coffee_->cost() + 0.70;
}
};
// 具体装饰器:奶泡
class Whip : public CoffeeDecorator {
public:
using CoffeeDecorator::CoffeeDecorator;
std::string getDescription() const override {
return coffee_->getDescription() + ", Whip";
}
double cost() const override {
return coffee_->cost() + 0.40;
}
};
void DecoratorPattern()
{
std::cout << std::string(13, '-') << " Decorator Pattern " << std::string(13, '-') << "\n";
// 基础咖啡
auto coffee = std::make_unique<Espresso>();
std::cout << coffee->getDescription() << ": $" << coffee->cost() << "\n";
// 加牛奶和摩卡
auto decoratedCoffee = std::make_unique<Mocha>(
std::make_unique<Milk>(std::move(coffee))
);
std::cout << decoratedCoffee->getDescription() << ": $"
<< decoratedCoffee->cost() << "\n";
// 再加奶泡
auto superCoffee = std::make_unique<Whip>(std::move(decoratedCoffee));
std::cout << superCoffee->getDescription() << ": $"
<< superCoffee->cost() << "\n";
}
组件对应关系
Coffee→ 组件接口Espresso→ 具体组件CoffeeDecorator→ 装饰器基类Milk/Mocha/Whip→ 具体装饰器
1387

被折叠的 条评论
为什么被折叠?



