设计模式学习笔记--装饰模式
2015-06-13 18:34
495 查看
定义:
在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。UML图:
形式:
(1) 装饰对象和真实对象有相同的接口。这样客户端对象就能以和真实对象相同的方式和装饰对象交互。(2) 装饰对象包含一个真实对象的引用(reference)
(3) 装饰对象接受所有来自客户端的请求。它把这些请求转发给真实的对象。
(4) 装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。
例子:
// 设计模式Demo.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <string> using namespace std; //要被装饰的对象基类(Component),这里用人物基类表示 class BaseCharacter { public: virtual void func() = 0; }; //要被修饰的对象(ConcreateComponent),这里用玩家表示 class Player : public BaseCharacter { public: void func() override { cout<<"I am Character. I don't have any equipment"<<endl; } }; //装饰基类(Decorator),这里用装备基类表示 class EquipmentBase : public BaseCharacter { private: BaseCharacter* m_pCharacter; public: void setCharacter(BaseCharacter* c) { m_pCharacter = c; } //重写function,执行character的func方法 void func() override { if (m_pCharacter) m_pCharacter->func(); } }; //具体装饰类(ConcreateDecorater),这里用武器表示 class Weapon : public EquipmentBase { private: //增加一个字段 string m_weapon; public: void func() override { //先执行基类的方法 EquipmentBase::func(); //执行装饰类特有的方法 m_weapon = "But now I have a gun!"; cout<<m_weapon<<endl; } }; //具体装饰类(ConcreateDecorater),这里用衣服表示 class Clothes : public EquipmentBase { public: void equipCloth() { cout<<"But now I have clothes"<<endl; } void func() override { EquipmentBase::func(); equipCloth(); } }; //客户端 int _tmain(int argc, _TCHAR* argv[]) { BaseCharacter* character = new Player(); Weapon* weapon = new Weapon(); Clothes* clothes = new Clothes(); /* 这里可能有些不太恰当,所说的装备并不是真正的装备,而是装备了装备的玩家 即通过了装备类,使玩家变成了有装备的玩家 */ //没有装备的玩家 cout<<"Before Equip:"<<endl; character->func(); //装备武器的玩家 cout<<"After Equip a weapon:"<<endl; weapon->setCharacter(character); weapon->func(); //再装备衣服的玩家 cout<<"After Equip clothes:"<<endl; clothes->setCharacter(weapon); clothes->func(); system("pause"); return 0; }这个例子写的是一个玩家和装备之间的关系,但是稍微有些不恰当,例子中的装备类并非仅仅表示一个装备,由于装备类继承了玩家类,所以这里表示的是装备了装备的玩家。
装饰模式通过装饰类,继承被装饰类,使装饰类自身和被装饰类接口相同。而内部封装了一个被装饰的对象引用(指针),我们可以更加灵活的在装饰类中添加要增加的代码,而且这样支持嵌套装饰,即有层次的装饰。如上面的例子,先装备武器再装备衣服。装饰模式可以动态的添加功能,就增加功能来说,比生成子类更加灵活。
什么时候使用装饰模式?
1.需要扩展一个类的功能时,装饰模式可以将装饰部分和原本的类的核心功能分开,这样更有利于功能划分。多用组合,少用继承!2.需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
3.需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。像上面的例子,想先穿衣服再拿武器也是可以的,而继承没法做到这点。
4.当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
相关文章推荐
- XenApp_XenDesktop_7.6实战篇之十二:组策略配置
- 解决mybatis foreach 错误: Parameter '__frch_item_0' not found
- (译)Getting Started——1.3.2 Using Design Patterns(使用设计模式)
- 过滤器实现统一编码
- Struts1防止表单重复提交
- SHELL中常用特殊变量
- 第二章 变量、数据类型和运算符
- 当主管对你说"今天这么早下班啊?",最好的回答是…
- 正则表达式基础用法
- kafka配置参数
- flash编程打地鼠游戏(1.思路)
- linux下的文件IO缓冲区,及其相关操作
- 前端思维导图
- Failed to fetch URL https://dl-ssl.google.com/android/repository/addons_list-2.xml, reason:
- 神经网络的理论基础
- RDIFramework.NET ━ .NET快速信息化系统开发框架 ━ 工作流程组件介绍
- CKEditor的基本使用
- 看懂gradle
- PHP面向对象-单列模式
- Java冠军程序员