0 引言

0.1 目的

       本文档给出设计模式之——Decorator模式的简化诠释,并给出其C++实现

0.2 说明

Project

Design Pattern ExplanationBy K_Eckel

Authorization

Free Distributed but Ownership Reserved

Date

2005-04-05Cherry blossom is Beautiful

Test Bed

MS Visual C++ 6.0

0.3 参考

       在本文档的写作中,参考了以下的资源,在此列出表示感谢:

u       书籍

[GoF 2000]GoF,Design Patterns-Elements of Reusable Object-Oriented Software

Addison-Wesley 2000/9.

        [Martine 2003]Robert C.Martine, Agile Software Development Principles, Patterns, and Practices, Pearson Education, 2003.

0.4 联系作者

Author

K_Eckel

State

Candidate for Master’s Degree School of Computer Wuhan University

E_mail

frwei@whu.edu.cn  

2 Decorator模式

2.1 问题

       OO设计和开发过程,可能会经常遇到以下的情况:我们需要为一个已经定义好的类添加新的职责(操作),通常的情况我们会给定义一个新类继承自定义好的类,这样会带来一个问题(将在本模式的讨论中给出)。通过继承的方式解决这样的情况还带来了系统的复杂性,因为继承的深度会变得很深。

       Decorator提供了一种给类增加职责的方法,不是通过继承实现的,而是通过组合。有关这些内容在讨论中进一步阐述。

2.2 模式选择

       Decorator模式典型的结构图为:


2-1Decorator Pattern结构图

      在结构图中,ConcreteComponentDecorator需要有同样的接口,因此ConcreteComponentDecorator有着一个共同的父类。这里有人会问,让Decorator直接维护一个指向ConcreteComponent引用(指针)不就可以达到同样的效果,答案是肯定并且是否定的。肯定的是你可以通过这种方式实现,否定的是你不要用这种方式实现,因为通过这种方式你就只能为这个特定的ConcreteComponent提供修饰操作了,当有了一个新的ConcreteComponent你又要去新建一个Decorator来实现。但是通过结构图中的ConcreteComponentDecorator有一个公共基类,就可以利用OO中多态的思想来实现只要是Component型别的对象都可以提供修饰操作的类,这种情况下你就算新建了100Component型别的类ConcreteComponent,也都可以由Decorator一个类搞定。这也正是Decorator模式的关键和威力所在了。

       当然如果你只用给Component型别类添加一种修饰,则Decorator这个基类就不是很必要了。

2.3 实现

2.3.1 完整代码示例(code

       Decorator模式的实现起来并不是特别困难,这里为了方便初学者的学习和参考,将给出完整的实现代码(所有代码采用C++实现,并在VC 6.0下测试运行)。

代码片断1Decorator.h
//Decorator.h

#ifndef _DECORATOR_H_
#define _DECORATOR_H_

class Component
{
public:
 virtual ~Component();

 virtual void  Operation();

protected:
 Component();

private:

};

class ConcreteComponent:public Component
{
public:
 ConcreteComponent();

 ~ConcreteComponent();

 void  Operation();

protected:

private:

};

class Decorator:public Component
{
public:
 Decorator(Component* com);

 virtual ~Decorator();

 void  Operation();

protected:
 Component* _com;

private:
};

class ConcreteDecorator:public Decorator
{
public:
 ConcreteDecorator(Component* com);

 ~ConcreteDecorator();

 void  Operation();

 void AddedBehavior();

protected:

private:

};

#endif //~_DECORATOR_H_

代码片断2Decorator.cpp
//Decorator.cpp

#include "Decorator.h"

#include <iostream>

Component::Component()
{

}

Component::~Component()
{

}

void Component::Operation()
{

}

ConcreteComponent::ConcreteComponent()
{

}

ConcreteComponent::~ConcreteComponent()
{

}

void ConcreteComponent::Operation()
{
 std::cout<<"ConcreteComponent operation..."<<std::endl;
}

Decorator::Decorator(Component* com)
{
 this->_com = com;
}

Decorator::~Decorator()
{
 delete _com;
}

void Decorator::Operation()
{

}

ConcreteDecorator::ConcreteDecorator(Component* com):Decorator(com)
{

}

ConcreteDecorator::~ConcreteDecorator()
{

}

void ConcreteDecorator::AddedBehavior()
{
 std::cout<<"ConcreteDecorator::AddedBehacior...."<<std::endl;
}
void ConcreteDecorator::Operation()
{
 _com->Operation();

 this->AddedBehavior();
}

 代码片断3main.cpp
//main.cpp

#include "Decorator.h"

#include <iostream>
using namespace std;

int main(int argc,char* argv[])
{
 Component* com = new ConcreteComponent();

 Decorator* dec = new ConcreteDecorator(com);

 dec->Operation();

 delete dec;

 return 0;
}

2.3.2 代码说明

Decorator模式很简单,代码本身没有什么好说明的。运行示例代码可以看到,ConcreteDecoratorConcreteComponent类添加了动作AddedBehavior

2.4 讨论

       Decorator模式和Composite模式有相似的结构图,其区别在Composite模式已经详细讨论过了,请参看相应文档。另外GoF在《设计模式》中也讨论到DecoratorProxy模式有很大程度上的相似,初学设计模式可能实在看不出这之间的一个联系和相似,并且它们在结构图上也很不相似。实际上,在本文档2.2节模式选择中分析到,让Decorator直接拥有一个ConcreteComponent的引用(指针)也可以达到修饰的功能,大家再把这种方式的结构图画出来,就和Proxy很相似了!

       Decorator模式和Proxy模式的相似的地方在于它们都拥有一个指向其他对象的引用(指针),即通过组合的方式来为对象提供更多操作(或者Decorator模式)间接性(Proxy模式)。但是他们的区别是,Proxy模式会提供使用其作为代理的对象一样接口,使用代理类将其操作都委托给Proxy直接进行。这里可以简单理解为组合和委托之间的微妙的区别了。

       Decorator模式除了采用组合的方式取得了比采用继承方式更好的效果,Decorator模式还给设计带来一种“即用即付”的方式来添加职责。在OO设计和分析经常有这样一种情况:为了多态,通过父类指针指向其具体子类,但是这就带来另外一个问题,当具体子类要添加新的职责,就必须向其父类添加一个这个职责的抽象接口,否则是通过父类指针是调用不到这个方法了。这样处于高层的父类就承载了太多的特征(方法),并且继承自这个父类的所有子类都不可避免继承了父类的这些接口,但是可能这并不是这个具体子类所需要的。而在Decorator模式提供了一种较好的解决方法,当需要添加一个操作的时候就可以通过Decorator模式来解决,你可以一步步添加新的职责。

Posted on 2005-07-08 21:05  k_eckel's mindview  阅读(969)  评论(0编辑  收藏  举报