【设计模式】装饰模式

1、定义

1.1 标准定义

装饰模式(Decorator Pattern)是一种比较常见的模式,其定义如下:Attach additionalresponsibilities to an object dynamically keeping the same interface.Decorators provide a flexiblealternative to subclassing for extending functionality.(动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。)

1.2 通用类图

● Component抽象构件

Component是一个接口或者是抽象类, 是定义我们最核心的对象, 就是最原始的对象。

注意:在装饰模式中,必然有一个最基本、最核心、最原始的接口或抽象类充当Component抽象构件。

● ConcreteComponent 具体构件

ConcreteComponent是最核心、最原始、最基本的接口或抽象类的实现,你要装饰的就是它。

● Decorator装饰角色

一般是一个抽象类,做什么用呢?实现接口或者抽象方法,它里面可不一定有抽象的方法呀,在它的属性里必然有一个private变量指向Component抽象构件。

● 具体装饰角色

ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰类, 你要把你最核心的、最原始的、最基本的东西装饰成其他东西。

2、实现

2.1 类图

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

ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。

Decorator为装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。

至于ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能。

要善于变通,如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。

同样道理,如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。

2.2 代码

2.2.1 装饰类

//Decorator.h

#ifndef _DECORATOR_H_
#define _DECORATOR_H_

//Component抽象类,定义该类对象的接口
class Component
{
public:
    virtual ~Component();
    virtual void Operation()=0;
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;
}

2.2.3 调用

// 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 0;
}

2.2.4 运行结果

3、优缺点

3.1 优点

● 装饰类和被装饰类可以独立发展,而不会相互耦合。换句话说,Component类无须知道Decorator类,Decorator类是从外部来扩展Component类的功能,而Decorator也不用知道具体的构件。
● 装饰模式是继承关系的一个替代方案。我们看装饰类Decorator,不管装饰多少层,返回的对象还是Component,实现的还是is-a的关系。
● 装饰模式可以动态地扩展一个实现类的功能,这不需要多说,装饰模式的定义就是如此 。

3.2 缺点

对于装饰模式记住一点就足够了:多层的装饰是比较复杂的。为什么会复杂呢?你想想看,就像剥洋葱一样,你剥到了最后才发现是最里层的装饰出现了问题,想象一下工作量吧,因此,尽量减少装饰类的数量,以便降低系统的复杂度。

4、应用场景

● 需要扩展一个类的功能, 或给一个类增加附加功能。
● 需要动态地给一个对象增加功能, 这些功能可以再动态地撤销。
● 需要为一批的兄弟类进行改装或加装功能, 当然是首选装饰模式。

时间: 2024-10-04 11:58:47

【设计模式】装饰模式的相关文章

c++设计模式----装饰模式

前言 在实际开发时,你有没有碰到过这种问题:开发一个类,封装了一个对象的核心操作,而这些操作就是客户使用该类时都会去调用的操作:而有一些非核心的操作,可能会使用,也可能不会使用:现在该怎么办呢? 将这些非核心的操作全部放到类中,这样,一个类就包含了很多核心的操作和一些看似有关,但是又无关的操作:这就会使核心类发生"爆炸"的现象,从而使核心类失去了一定的价值,也使使用核心类的客户在核心操作和非核心操作中挣扎: 使用继承来扩展核心类,需要使用核心类时,直接建立核心类对象:当需要使用核心类扩

设计模式——装饰模式(Decorator)

要想正确理解设计模式,首先必须明确它是为了解决什么问题而提出来的. 设计模式学习笔记 --Shulin 转载请注明出处:http://blog.csdn.net/zhshulin 1.概念 装饰模式又名包装(Wrapper)模式.装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 但是纯粹的装饰模式很难找到,大多数的装饰模式的实现都是"半透明"的,而不是完全透明的.换言之,允许装饰模式改变接口,增加新的方法.半透明的装饰模式是介于装饰模式和适配器模式之间的.适配器模

设计模式—装饰模式和适配器模式

装饰模式又名包装(Wrapper)模式.装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 设计模式在JAVA I/O库中的应用 装饰模式在Java语言中的最著名的应用莫过于Java I/O标准库的设计了. 由于Java I/O库需要很多性能的各种组合,如果这些性能都是用继承的方法实现的,那么每一种组合都需要一个类,这样就会造成大量性能重复的类出现. 而如果采用装饰模式,那么类的数目就会大大减少,性能的重复也可以减至最少.因此装饰模式是Java I/O库的基本模式. 适配器模

将计算机思维故事化——之设计模式装饰模式

"我要买一个装东西的袋子" --如果需要搬家里的行李,这句话可能会发生在超市里. 那么,上述提到的三个名词--"东西"."袋子"和"行李",应该是如下图关系: (1)行李,是一样东西 (2)袋子,也是一样东西 (3)袋子,可以装行李 通过以上三句话的关系,可以得出结论:第一,袋子可以装东西,虽然其本身就是一样东西:第二,装了东西的袋子,还是一样东西.所以,可以在行李的基础上,不断地套袋子,且不管加多少层,最后得到的还是一样东西

大话设计模式-装饰模式(C++)

<大话设计模式>的装饰模式的C++实现. 结构图: Decorator.h: #ifndef _DECORATOR_H #define _DECORATOR_H #include <iostream> #include <string> using namespace std; //ConcreteComponent类 class CPerson { public: CPerson(){}; CPerson(string str):m_sName(str){}; vir

小菜学设计模式——装饰模式

背景 很多时候你会发现子类在不断增加,有时候甚至难以控制,虽然继承是面向对象的一大特征,但是继承并不是项目中所提倡,合成复用设计原则就告诉我们能够使用合成的地方尽量不要使用继承.对于继承来说还有一个很大的缺点,那就是内存占用与子类的层次是成正比关系的,这个也很好理解,实例化子类的时候总是要先调用最顶层父类的构造方法,然后依次调用低层次的父类直到自身初始化,这个过程实际上是很耗内存的.那么,问题就来了,我们经常会扩展一个类的某个方法,是不是没扩展方法都有必要新增一个子类呢?答案是否定的,在某种情况

大话设计模式—装饰模式

装饰模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能. 大话设计模式中程杰老师给出的定义,装饰模式:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活. 装饰模式结构图如下: 关键代码: 1.Component 类充当抽象角色,不应该具体实现. 2.修饰类引用和继承

Java设计模式----装饰模式

1.概念: (在我看来,模式就像是是一种思想,在这种思想的指引下,对代码和结构的一番加工和整合而已!都是套路!) 装饰模式又称包装(Wrapper)模式,是以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案.对客户端透明意味着接口不变. 2.问题: 在OO设计和开发过程中, 经常会遇到下面的情况: 我们需要为已经设计好的类添加新的职责, 通常情况下我们会定义一个新类继承自定义好的类. 由于组合比继承更好(复杂度高,继承深度深等原因, 类图: 3.如何实现装饰: (1):继承形式:(不推

设计模式--装饰模式

装饰模式用例图 class Program { static void Main(string[] args) { ConcreteComponent c = new ConcreteComponent(); ConcreteDecoratorA d1 = new ConcreteDecoratorA(); ConcreteDecoratorB d2 = new ConcreteDecoratorB(); d1.SetComponent(c); d2.SetComponent(d1); d2.O

[工作中的设计模式]装饰模式decorator

一.模式解析 装饰模式又名包装(Wrapper)模式.装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰模式的要点主要是: 1.需要对已有对象扩展新的功能,又不希望改变原有对象接口: 2.装饰者对象与原有对象需要继承相同接口,初始化装饰对象时将原有对象传入装饰对象: 3.可以对一个对象定义多个装饰着对象,进行分别装饰或者组合装饰 二.模式代码 1.抽象接口 package decorator.patten; public interface Component { pu