设计模式之装饰者模式
来源:互联网 发布:女性健康知讲座 编辑:程序博客网 时间:2024/06/05 00:47
一、模式动机
使用继承可以给现有类添加行为,但是这种方法是静态的,用户不能控制增加行为的方式和时机。因此可以使用关联机制,即将一个类的对象嵌入另一个对象中,由另一个对象来决定是否调用嵌入对象的行为以便扩展自己的行为,我们称这个嵌入的对象为装饰器(Decorator)
装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任,换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。这就是装饰模式的模式动机。
二、模式定义
装饰者模式(Decorator Pattern):动态地将责任附加到对象上。如要扩展功能,装饰者提供了比继承更有弹性的替代方案。包括抽象组件、具体组件、抽象装饰者和具体装饰者。
三、模式示例
星巴兹咖啡连锁店由于扩张速度太快了,准备更新订单系统,以满足他们的饮料供应要求。他们的类设计如下:
购买咖啡,可以要求在其中加入配料,例如:牛奶,摩卡等。星巴兹会根据所加入的配料收取不同的费用。价格表如下:
如果用继承的话,设计出很多类。采用装饰者模式来解决问题,UML类图如下:
C++代码实现
#include <string>#include <iostream>#include "windows.h"using namespace std;class Beverage{public: virtual double cost() = 0; virtual string getDescription() const { return description_; } Beverage(); ~Beverage();protected: string description_;};Beverage::Beverage() :description_("Unknown Beverage"){}Beverage::~Beverage(){}//综合class HouseBlend : public Beverage{public: double cost() { return 0.89; } string getDescription() const { return description_; } HouseBlend(); ~HouseBlend();};HouseBlend::HouseBlend(){ description_ = "HouseBlend";}HouseBlend::~HouseBlend(){}//浓缩咖啡class Espresso : public Beverage{public: double cost() { return 1.99; } string getDescription() const { return description_; } Espresso(); ~Espresso();};Espresso::Espresso(){ description_ = "Espresso";}Espresso::~Espresso(){}//深焙咖啡class DarkRoast : public Beverage{public: double cost() { return 0.99; } string getDescription() const { return description_; } DarkRoast(); ~DarkRoast();private:};DarkRoast::DarkRoast(){ description_ = "DarkRoast";}DarkRoast::~DarkRoast(){}//低咖啡因class Decaf : public Beverage{public: double cost() { return 1.05; } string getDescription() const { return description_; } Decaf(); ~Decaf();};Decaf::Decaf(){ description_ = "Decaf";}Decaf::~Decaf(){}//抽象装饰者:调料Condimentclass Condiment : public Beverage{public: Condiment(Beverage* beverage); ~Condiment();protected: Beverage* beverage_;};Condiment::Condiment(Beverage* beverage) :beverage_(beverage){}Condiment::~Condiment(){}//调料:摩卡class Mocha : public Condiment{public: double cost(){ return 0.2 + beverage_->cost(); } string getDescription() const { return beverage_->getDescription() + " , Mocha"; } Mocha(Beverage* beverage); ~Mocha();};Mocha::Mocha(Beverage* beverage) :Condiment(beverage){}Mocha::~Mocha(){}//调料:牛奶class Milk : public Condiment{public: double cost(){ return 0.1 + beverage_->cost(); } string getDescription() const { return beverage_->getDescription() + " , Milk"; } Milk(Beverage* beverage); ~Milk();};Milk::Milk(Beverage* beverage) :Condiment(beverage){}Milk::~Milk(){}//调料:豆浆class Soy : public Condiment{public: double cost(){ return 0.15 + beverage_->cost(); } string getDescription() const { return beverage_->getDescription() + " , Soy"; } Soy(Beverage* beverage); ~Soy();};Soy::Soy(Beverage* beverage) :Condiment(beverage){}Soy::~Soy(){}//调料:奶泡class Whip : public Condiment{public: double cost(){ return 0.1 + beverage_->cost(); } string getDescription() const { return beverage_->getDescription() + " , Whip"; } Whip(Beverage* beverage); ~Whip();};Whip::Whip(Beverage* beverage) :Condiment(beverage){}Whip::~Whip(){}int _tmain(int argc, _TCHAR* argv[]){ Beverage* beverage = new Espresso; cout << beverage->getDescription() << " $" << beverage->cost() << endl; beverage = new Mocha(beverage); cout << beverage->getDescription() << " $" << beverage->cost() << endl; beverage = new Milk(beverage); cout << beverage->getDescription() << " $" << beverage->cost() << endl; beverage = new Soy(beverage); cout << beverage->getDescription() << " $" << beverage->cost() << endl; beverage = new Whip(beverage); cout << beverage->getDescription() << " $" << beverage->cost() << endl; system("pause"); return 0;}
运行结果
四、分析总结
装饰模式用于动态地给一个对象增加一些额外的职责,就增加对象功 能来说,装饰模式比生成子类实现更为灵活。它是一种对象结构型模 式。
优点:
- 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。
- 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的装饰器,从而实现不同的行为。
- 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
- 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”
缺点:
- 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,同时还将产生很多具体装饰类。这些装饰类和小对象的产生将增加系统的复杂度,加大学习与理解的难度。
- 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。
阅读全文
0 0
- 设计模式之装饰者设计模式
- 设计模式 之 装饰者
- 设计模式之装饰者模式
- 设计模式之装饰者模式
- 设计模式之Decorator(装饰者模式)
- 设计模式之五---装饰者模式
- 设计模式之---装饰者模式
- c++设计模式之装饰者模式
- Php设计模式之装饰者模式
- java设计模式之装饰者模式
- 设计模式之装饰者模式
- 【设计模式】之装饰者模式
- HeadFirst设计模式之装饰者模式
- c++设计模式之装饰者模式
- 设计模式之装饰者模式
- 设计模式之--装饰者模式
- 设计模式之装饰者模式
- 设计模式之装饰者模式
- tensorlow函数多个返回值问题
- 利用网络传输系统的声音
- Web开发中服务器转发方式forward和redirect的区别
- Centos 7 安装 memcached
- UINavigationBar 和 UITabBarItem 属性设置
- 设计模式之装饰者模式
- [LeetCode] 2Sum, 3Sum, 4Sum小结
- Python基础入门(5)
- 安装Nvidia显卡驱动和CUDA
- 汉诺塔
- sql update操作数据更新成功,返回的影响行数是0
- 111
- ajax注册验证
- python中关于时间用法