【2013.1.27】诸葛先生,你到底亮不亮?——Decorator

来源:互联网 发布:努比亚z11mini网络 编辑:程序博客网 时间:2024/05/02 04:31

// // // // // // // // //

///2013.1.27

// // // // // // // // //

还记得前些天流行这样一个网络文化:

给名人找亲戚。


比如说诸葛亮先生,

不完全统计,

其有以下几个兄弟:

诸葛暗,诸葛闪光,诸葛亮不亮……


诸葛先生的兄弟们同样也神通广大,

每一个都喜欢自比管仲、乐毅,

每一个都能未出茅庐而心中已三分天下,

每一个都能在兵临城下之际而于空城之上淡然弹琴,

每一个都能在冬天岿然不动地扇扇子,

……

除此之外,

每一个都拥有自己的特色:

例如诸葛暗先生在晚上出去可以冒充包大人。。。等


那么,

我们该如何实现这些兄弟呢?


很容易的想到让拥有基础本领的诸葛亮作为基类,

每一个兄弟都去继承他,

再分别添加上自己的独家本领。


如果只有几个的话,

这个方法是没有问题的。


但是如果发动网友寻找诸葛家族百年史的话,

找出来几百万个诸葛XXX,

也都要继承么?


诸葛亮要告诉每个兄弟自己的本领,

然后告诉他们你们也有这些本领(基类功能)。

不管诸葛亮会不会累死,

但等到每个人都知道的时候(程序编译完成,准备执行),

估计上帝都看不到了。


这个时候,

躲在角落里的Decorator模式笑了。


该它出场了。


【核心】Decorator通过继承并聚合基类,并在构造器中将其实例化,从而在不改变原有功能的基础之上实现功能的扩展。


UML图:



Component是基类(诸葛亮先生),

ConcreteComponent是其功能的实现(传入Decorator的构造器中)。

至于ConcreteDecoratorA与ConcreteDecoratorB则是对Decorator实现不同功能的扩展了(就像诸葛暗与诸葛闪光之间的关系)


在一开始我对Decorator有这样一个困惑,

就是为什么不直接将Component基类组合在Decorator之中,

还要再加一个继承关系呢?

不是能够到达同样的效果的么?


后来我仔细想了一下,

忽然发现自己犯了一个很没智商的问题:

如果只用组合的话,

还是设计模式么?

除此之外,

在网上找到了一个更为确切的答案,能够解决这一困惑:

Decorator是能够忠实地调用原有接口的基础上,进行功能的扩展。

脱离了继承关系,

谁知道你这个装饰器中还有原来方法的调用?(除此之外还有Protected类型不能访问的因素)


其实Decorator模式也是与Proxy,Composite等模式有相像之处的。

具体的区别会在日后涉及到此等模式时再详述。


设计模式之间很多都是共同的,

但是告诉大家一个记忆的方法,

就是名称记忆。

每一个模式的结构,

必然是围绕着其名称而实现的。


比如说Decorator名字就是装饰器,

因此它的功能就是装饰。

装饰是什么?

是添加扩展,在不改变原有结构的基础上,

方便地实现各种功能(取决于传入的Component实例)的扩展。


这个设计模式被广泛的应用于各种平台的Widget(控件)设计之中。

比如说InputWidget,其子类有Number_InputWidget,Char_InputWidget等(泛指)。

Button,其子类有ImageButton,AnimationButton等。


代码实例:


【大致思路】

BaseComponent作为最基础的接口,实现了此接口的ConcreteComponent用于实现具体功能。

同样继承了BaseComponent的Decorator内部封装一个BaseComponent类型的的指针,并在构造器中进行实例实例化。


Decorator.h

#ifndef _DECORATOR_H_#define _DECORATOR_H_class BaseComponent{public:BaseComponent(){}~BaseComponent(){}virtual void Execute() = 0;};class ConcreteComponent:public BaseComponent{public:ConcreteComponent(){}~ConcreteComponent(){}void Execute();};class Decorator: public BaseComponent{public:Decorator(BaseComponent* com);~Decorator(){}virtual void Execute(){}protected:BaseComponent* component;};class ConcreteDecorator: public Decorator{public:ConcreteDecorator(BaseComponent* com);~ConcreteDecorator(){}void Execute();};#endif

Decorator.cpp

#include "Decorator.h"#include<iostream>void ConcreteComponent::Execute(){std::cout<<"Execute base function."<<std::endl;}Decorator::Decorator(BaseComponent* com):component(com){}ConcreteDecorator::ConcreteDecorator(BaseComponent* com):Decorator(com){}void ConcreteDecorator::Execute(){//Execute base function.component->Execute();//Add extra function.std::cout<<"Add Extra function."<<std::endl;}

main.cpp

#include"Decorator.h"int main(){BaseComponent* baseComponent = new ConcreteComponent();Decorator* newComponent = new ConcreteDecorator(baseComponent);newComponent->Execute();return 0;}

输出结果:



【注意事项】

或许会有人疑惑ConcreteDecorator是干什么用的,

——完全可以在Decorator中实现所有的附加功能。

但这里要声明一点的是,

Decorator类一定不能用来实现具体的功能(小规模除外),

真正的实现过程要在ConcreteDecorator中进行。

这次的代码示例中的"装饰功能"只是多输出一行文字。

但是如果有更多的状态,更多的功能,

再把这些都集成到Decorator中,

那Decorator将变得拥挤不堪,

——自然也将失去Decorator模式的本意。


另外,

ConcreteComponent也是同样的道理,

就像是Widget类的子类Button,TextField,Image一样,

内部集成不同的基础功能。


原创粉丝点击