侃装饰模式(Decorator)

        装饰模式可以在不改变现有类的情况下向其中添加新方法。(敏捷软件开发-原则 模式与实践 Robert C. Martin)这是Martin对装饰模式作用的说明,他也举了个modem的例子。这句话的意思是一点不改变现有类的代码而向其中添加新方法。那么有人会问,如果我有代码,有些时候我是否直接把新的方法加在已有的类中来的简单呢?是的,在特定的时期直接加在类中来的简洁,但有些时候,虽然你有类的源代码,但你的类是在动态库中,并且动态库已经发布,而且有用户在使用这个动态库了,这时修改类就不是那么容易了,牵一发而动全身。

        下面这张UML图就是一个典型的装饰。CDoor是一个借口类,它有开和关两种操作。 



而红色标记的是不能修改的类。为了建设文明城市,客户要求要为商场里的门加一个功能,就是在门打开后,要播放“欢迎光临”的声音。这时装饰模式就派上用场了。建一个CSayWelcomeDecorator类,对CShopDoor类进行装饰,在CSayWelcomeDecorator中有一个CDoor的对象。客户调用的代码如下(C++ 语言): 

     CDoor*    pDoor = new CShopDoor(); 
     CSayWelcomeDecorator *pSayWelcomeDecorator= new CSayWelcomeDecorator (pDoor ); 
     pSayWelcomeDecorator->Open(); 

    让我们来看看它是如何工作的。 
    首先是把pDoor委托给pSayWelcomeDecorator对象,然后调用pSayWelcomeDecorator->Open()函数,在Open函数中会先把门打开,这就是调用pDoor->Open() ,然后说“欢迎光临”,就是调用pSayWelcomeDecorator中的SayWelcome()函数,这样就给pDoor对象加上了一个新方法,而没有改变原来的类结构。
    现在有顾客反映说,开门说“欢迎光临”很烦人,顾客是上帝,所有现在要移除这个功能,那也很简单,只要修改调用的地方,把装饰类去掉就行了。代码如下:
    CDoor*    pDoor = new CShopDoor(); 
     pDoor ->Open(); 
这就如吕震宇所写道的:可以动态地给一个对象增加功能,这些功能可以再动态地撤销。

    现在人民的生活越来越好,家里都用上了密码锁,而且开了门还能说“欢迎回来”的话。让我们来看看在上面的基础上如何实现此功能。


代码如下:
CHomeDoor*    pHomeDoor = new CHomeDoor();
CDoorDecorator *pSayWelcomeDecorator = new CSayWelcomeDecorator(pHomeDoor );
CDoorDecorator *pPasswordDecorator = new CPasswordDecorator(pSayWelcomeDecorator );
pPasswordDecorator->Open();
那么它是如何工作的呢?让我们来分析分析。在 pPasswordDecorator 对象的Open函数中是这样调用的:
if(CheckPassword() == TRUE)
    m_pDoor->Open();
else
    Warning();
当密码检查正确,它就继续调用pSayWelcomeDecorator对象的Open函数,结果就和上面的一样,当密码检查错误,就马上报警,也就进不了门了。
多个装饰类装饰一个对象,组合了多个单独的功能,这就是它的功能。

     以上是我对装饰模式的理解,如果理解有偏差,还望赐教。

    
 
原文地址:https://www.cnblogs.com/goodcandle/p/DecoratorPattern.html