1. 概述

若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性。如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继承这个类来产生一个新类—这建立在额外的代码上。

通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法。但是这种方法是静态的,用户不能控制增加行为的方式和时机。如果  你希望改变一个已经初始化的对象的行为,你怎么办?或者,你希望继承许多类的行为,改怎么办?前一个,只能在于运行时完成,后者显然时可能的,但是可能会导致产生大量的不同的类—可怕的事情。

2. 问题

你如何组织你的代码使其可以容易的添加基本的或者一些很少用到的 特性,而不是直接不额外的代码写在你的类的内部?

3. 解决方案

装饰器模式: 动态地给一个对象添加一些额外的职责或者行为。就增加功能来说, Decorator模式相比生成子类更为灵活。

装饰器模式提供了改变子类的灵活方案。装饰器模式在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

当用于一组子类时,装饰器模式更加有用。如果你拥有一族子类(从一个父类派生而来),你需要在与子类独立使用情况下添加额外的特性,你可以使用装饰器模式,以避免代码重复和具体子类数量的增加。

4. 适用性

以下情况使用Decorator模式

1)• 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

2)• 处理那些可以撤消的职责。

3)• 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,

为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。

另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

5. 结构

UML图如下

Component是定义一个对象接口,可以给这些对象动态地添加职责。

ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。
Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。
至于ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能。

要善于变通,如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。
同样道理,如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。

新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为 的需要。而装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为 时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了。

代码如下

Decorator.h

#ifndef _DECORATOR_H_
#define _DECORATOR_H_ //Component抽象类,定义该类对象的接口
class Component
{
public:
virtual ~Component();
virtual void Operation()=;
protected:
Component();
}; //ConcreteDecorator:具体的Component对象,可以给该对象动态 添加职责
class ConcreteComponent:public Component
{
public:
ConcreteComponent();
~ConcreteComponent();
virtual void Operation();
}; //Decorator:装饰抽象类,继承自Component
class Decorator:public Component
{
public:
Decorator(Component* com);
void SetComponent(Component* com);
virtual ~Decorator();
virtual void Operation();
protected:
Component* _com;
}; //ConcreteDecorator就是具体的装饰对象之一,起到给Component添加职责的功能
class ConcreteDecoratorA:public Decorator
{
public:
ConcreteDecoratorA(Component* com);
~ConcreteDecoratorA();
virtual void Operation();
void AddBehavorA();
}; //ConcreteDecorator就是具体的装饰对象之二,起到给Component添加职责的功能
class ConcreteDecoratorB:public Decorator
{
public:
ConcreteDecoratorB(Component* com);
~ConcreteDecoratorB();
virtual void Operation();
void AddBehavorB();
}; //ConcreteDecorator就是具体的装饰对象之三,起到给Component添加职责的功能
class ConcreteDecoratorC:public Decorator
{
public:
ConcreteDecoratorC(Component* com);
~ConcreteDecoratorC();
virtual void Operation();
void AddBehavorC();
}; //ConcreteDecorator就是具体的装饰对象之四,起到给Component添加职责的功能
class ConcreteDecoratorD:public Decorator
{
public:
ConcreteDecoratorD(Component* com);
~ConcreteDecoratorD();
virtual void Operation();
void AddBehavorD();
}; //只添加一种装饰,则不用抽象出装饰基类
class DecoratorOnlyOne:public Component
{
public:
DecoratorOnlyOne(Component* com);
~DecoratorOnlyOne();
virtual void Operation();
void AddBehavor();
private:
Component* _com;
}; //如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。
//略
#endif

Decorator.cpp

#include "Decorator.h"
#include <iostream> using namespace std; Component::Component()
{} Component::~Component()
{
cout << "~Component" << endl;
} ConcreteComponent::ConcreteComponent()
{} ConcreteComponent::~ConcreteComponent()
{
cout << "~ConcreteComponent" << endl;
} void ConcreteComponent::Operation()
{
cout << "原职责:ConcreteComponent::Operation" << endl;
} Decorator::Decorator(Component* com)
{
this->_com = com;
} void Decorator::SetComponent(Component* com)
{
this->_com = com;
} Decorator::~Decorator()
{
cout << "~Decorator" << endl;
delete this->_com;
this->_com = NULL;
} void Decorator::Operation()
{} ConcreteDecoratorA::ConcreteDecoratorA(Component* com):Decorator(com)
{} ConcreteDecoratorA::~ConcreteDecoratorA()
{
cout << "~ConcreteDecoratorA" << endl;
} void ConcreteDecoratorA::Operation()
{
this->_com->Operation();
//附加职责A
this->AddBehavorA();
} void ConcreteDecoratorA::AddBehavorA()
{
cout << "附加职责A:ConcreteDecoratorA::AddBehavorA" << endl;
} ConcreteDecoratorB::ConcreteDecoratorB(Component* com):Decorator(com)
{} ConcreteDecoratorB::~ConcreteDecoratorB()
{
cout << "~ConcreteDecoratorB" << endl;
} void ConcreteDecoratorB::Operation()
{
this->_com->Operation();
//附加职责B
this->AddBehavorB();
} void ConcreteDecoratorB::AddBehavorB()
{
cout << "附加职责B:ConcreteDecoratorB::AddBehavorB" << endl;
} ConcreteDecoratorC::ConcreteDecoratorC(Component* com):Decorator(com)
{} ConcreteDecoratorC::~ConcreteDecoratorC()
{
cout << "~ConcreteDecoratorC" << endl;
} void ConcreteDecoratorC::Operation()
{
this->_com->Operation();
//附加职责C
this->AddBehavorC();
} void ConcreteDecoratorC::AddBehavorC()
{
cout << "附加职责C:ConcreteDecoratorC::AddBehavorC" << endl;
} ConcreteDecoratorD::ConcreteDecoratorD(Component* com):Decorator(com)
{} ConcreteDecoratorD::~ConcreteDecoratorD()
{
cout << "~ConcreteDecoratorD" << endl;
} void ConcreteDecoratorD::Operation()
{
this->_com->Operation();
//附加职责D
this->AddBehavorD();
} void ConcreteDecoratorD::AddBehavorD()
{
cout << "附加职责D:ConcreteDecoratorD::AddBehavorD" << endl;
} //**************只添加一种修饰******************
DecoratorOnlyOne::DecoratorOnlyOne(Component* com):_com(com)
{
} DecoratorOnlyOne::~DecoratorOnlyOne()
{
cout << "~DecoratorOnlyOne" << endl;
delete this->_com;
this->_com = NULL;
} void DecoratorOnlyOne::Operation()
{
this->_com->Operation();
this->AddBehavor();
} void DecoratorOnlyOne::AddBehavor()
{
cout << "附加唯一职责:DecoratorOnlyOne::AddBehavor" << endl;
}

main.cpp

#include "Decorator.h"
#include <iostream> using namespace std;
int main()
{
Component* pCom = new ConcreteComponent(); //要装饰的对象
Decorator* pDec = NULL;
pDec = new ConcreteDecoratorA(pCom); //给装饰对象附加职责A
pDec = new ConcreteDecoratorB(pDec); //给装饰对象附加职责B
pDec = new ConcreteDecoratorC(pDec); //给装饰对象附加职责C
pDec = new ConcreteDecoratorD(pDec); //给装饰对象附加职责D
pDec->Operation(); cout << "-------------------------------" << endl; //只添加一种修饰
Component* pCom1 = new ConcreteComponent();
DecoratorOnlyOne* pDec1 = new DecoratorOnlyOne(pCom1);
pDec1->Operation(); cout << "-------------------------------" << endl; delete pDec;
cout << "-------------------------------" << endl; delete pDec1; return ;
}

总结

一般,当系统需要新功能的时候,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为,但这种做法的问题在于,它们在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度,并且新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要。而装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了。

那么装饰模式的优点有:1 把类中的装饰功能从类中搬移去除,这样可以简化原有的类,这样做更大的好处就是有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。

Decorator(装饰)模式的更多相关文章

  1. 十、装饰(Decorator)模式 --结构模式(Structural Pattern)

    装饰(Decorator)模式又名包装(Wrapper)模式[GOF95].装饰模式以对客户端透明的方 式扩展对象的功能,是继承关系的一个替代方案. 装饰模式类图: 类图说明: 抽象构件(Compon ...

  2. 设计模式的征途—10.装饰(Decorator)模式

    虽然目前房价依旧很高,就连我所在的成都郊区(非中心城区)的房价均价都早已破万,但却还是阻挡不了大家对新房的渴望和买房的热情.如果大家买的是清水房,那么无疑还有一项艰巨的任务在等着大家,那就是装修.对新 ...

  3. Decorator装饰者模式(结构型模式)

    1.需求 假设让我们去设计FCL中的Stream类,该类具有流类的基本功能,除了有各种不同类型的流外(如内存流.文件流.网络流等等),但是在不同的业务场景下,如处理银行业务,需要给相关的内存流进行加密 ...

  4. ④ 设计模式的艺术-10.装饰(Decorator)模式

    职责 装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象. 装饰模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对 ...

  5. 设计模式:装饰器(Decorator)模式

    设计模式:装饰器(Decorator)模式 一.前言    装饰器模式也是一种非常重要的模式,在Java以及程序设计中占据着重要的地位.比如Java的数据流处理,我们可能看到数据流经过不同的类的包装和 ...

  6. 装饰(Decorator)模式

    一. 装饰(Decorator)模式 装饰(Decorator)模式又名包装(Wrapper)模式[GOF95].装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 二. 装饰模式 ...

  7. 设计模式之装饰(Decorator)模式

    设计模式之装饰(Decorator)模式 (一)什么是装饰(Decorator)模式 装饰模式,又称为包装模式,它以对客户端透明的方式扩张对象的功能,是继承关系的替代方案之一. 装饰模式可以在不使用创 ...

  8. Decorator 装饰(结构型)

    Decorator 装饰(结构型) 一:描述: Decorator装饰模式是动态地给一个对象增加一些额外的功能职责特性. 来替换以前使用的继承来静态扩展对象的功能,避免子类的增多,做到更灵活: 注:和 ...

  9. Python进阶之decorator装饰器

    decorator装饰器 .note-content {font-family: "Helvetica Neue",Arial,"Hiragino Sans GB&quo ...

  10. 谈谈Python中的decorator装饰器,如何更优雅的重用代码

    众所周知,Python本身有很多优雅的语法,让你能用一行代码写出其他语言很多行代码才能做的事情,比如: 最常用的迭代(eg: for i in range(1,10)), 列表生成式(eg: [ x* ...

随机推荐

  1. 浏览器根对象window之Location

    1. Location Location 对象包含有关当前 URL 的信息.Location 对象是 Window 对象的一个部分,可通过 window.location 属性来访问. 1.1 Loc ...

  2. Java设计模式—状态模式

    状态模式又是一个比较难的设计模式 定义如下: 当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类. 个人理解:通俗的讲,状态模式就是状态的改变引起了行为的改变,但是,我们只能看到行为的 ...

  3. Linux 新手入门常用命令

    1,增加用户:useradd mylinux passwd mylinux 添加你的用户密码 2,切换用户: su otheruser   (注意这种切换方式只是临时的,本质工作目录还在原来的用户目录 ...

  4. SpringBoot整合Slf4j+logback日志框架

    一.Slf4j简单介绍与优势 1.介绍 Slf4j的全称是Simple Loging Facade For Java(Java简单日志门面),它仅仅是一个为Java程序提供日志输出的统一接口,并不是一 ...

  5. Linux下vim(文本编译器)的使用

    vim (文本编译器): Vim是从 vi 发展出来的一个文本编辑器. vim的一些命令操作: 插入命令: a 在光标所在字符后插入 A 在光标所在行尾插入 i 在光标所在字符前插入 I 在光标所在行 ...

  6. Redis的基本操作语句

    注:以下出现的key.value都需要具体 1.String类型的数据存储获取 set key value:设置key的值为value,若存在则覆盖,不存在则自动创建decrby get key:获取 ...

  7. Java基础之JSONObject的使用

    private static JSONObject createJSONObject() { JSONObject jsonObject = new JSONObject(); jsonObject. ...

  8. 数据迁移:MSSQL脚本文件过大,客户端没有足够的内存继续执行程序

    在CMD窗口(俗称:黑屏程序) 下输入 SQLCMD 命令 命令格式如下: sqlcmd -U 用户名   -P 密码    -S 服务器地址   -d 数据库名称  -i  你的脚本文件.sql ( ...

  9. python之路——进程

    操作系统背景知识 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操作系统的其 ...

  10. [翻译] JNWSpringAnimation

    JNWSpringAnimation https://github.com/jwilling/JNWSpringAnimation JNWSpringAnimation is a subclass o ...