读GOF设计模式杂记之 Decorator

   
    模式名:Decorator
    意图:“动态地” 给一个“对象” 添加一些额外的职责。
    这句话是相对于“静态地” 给一个类添加功能说的。当需要给一个对象增加功能的时候可以有以下两种选择:
      (1) 一种选择是在这个对象的类上添加额外的功能代码。
            缺点: 第一种方式会造成所有的这个类的对象其行为都发生改变。
      (2) 第二种选择是为这个类派生一个子类用来增加其功能。
           缺点: 第二种方式利用了面向对象思想的继承和多态特性,它可以在不改变其他对象的前提下产生一个派生类型来增加功能。不过这样做有一点不足就是会造成类数量的爆 炸。例如有100动物的类,他们有共同的基类“动物”。其中的30种动物成长到一定年龄就会有飞翔的功能,需要给这30种动物增加飞翔的功能。如果利用第 二种方式就会增加30个派生类来表示那些成长到一定年龄的会飞翔的动物。而且如果我想找一种飞翔的动物来送信那么就需要静态的(对于静态语言,如果是动态 语言就没有这个问题了)选择好那种动物。
    用法:这时我们就可以使用Decorator模式来解决我们的问题。
          我们还以刚才的那个例子来说明问题。我们从“动物”基类派生一个flyAmnimal,这个类包含一个指向其他动物的指针,并把基类的接口 (virtual 接口)都映射到所指向的动物身上。另外为所指向的动物增加一个飞翔功能。这个flyAnimal就是一个 decorator模式的类。
    优点:代码复用,我们不用在为不同的类定义多个派生类。避免生成多个派生类来重复添加某一特征。
              更为灵活,可以动态指定使用那种飞翔的动物来送信。
     缺点:代码结构更为复杂,系统更难理解,对于对系统不是很了解的人来说,很难为其增加功能。排错也更困难。
               当所修饰的对象非常大的时候,decorator的代价就会很高。可以考虑使用stategy模式替代。
    注意: 接口一致性,修饰类和被修饰类必须要相同的接口,也就是有共同的基类。
               可以省略抽象的Decorator。仅需要增加一个职责的时候Decorator可以只有一个而不是一个Decorator树。
             
    和Strategy模式的比较:
            Decorator可以看作是改变一个对象的外壳,不改变其已有的内核。只是给对象增加一些功能。Decorator对象在组件对象的外部。
            Strategy模式却是改变对象的内核,给对象一组可选的内核功能。Strategy的对象在组件对象的内部。
    和composite模式的比较:
           Decorator可以看作一个退化了的,只有一个组建的composite,同时还可以看作一个增强了功能的composite。它弱化了composite的聚集对象的功能,却强化了唯一一个component的能力。


一个例子:
/*
*file name:animal.cpp
*description:一个简单的decorator模式的例子
* author: yingjie
* */
#include <iostream>
using namespace std;

/*
* 定义animal基类
* */
class animal
{
public:
    virtual string name() const = 0;
    virtual void run()const {cout << "I am runing!" << endl;}
    virtual ~animal(){}
};

/*
*animal 派生的eagle
* */
class eagle:public animal
{
    string name()const {return string("eagle"); }
};

/*
*animal 派生的dove
* */
class dove:public animal
{
    string name()const {return string("dove"); }
};

/*
*animal 派生的birdmen
* */
class birdmen:public animal
{
    string name()const {return string("birdmen"); }
};

/*
*最关键的decorator类,它和eagle,dove一样继承自animal,它拥有一个指向animal的指针,并且把基类所有的virtual函数映射到所指向的animal的实现中。然后添加自己修饰函数
* */
class flyAnimal:public animal
{
public:
    flyAnimal():p(0){}
    flyAnimal(animal * ptr):p(ptr){}
    void setAnimal(animal * ptr){delete p;p = ptr;}

    //把基类的virtual函数“全部”映射到所修饰的对象的实现上。
    string name()const  
    {
        if (p) return p->name();
        return "no decorated animal!";
    }    
    void run()const{if (p) p->run();}

    void fly()const{if (p) cout << "I am flying!" << endl;} //添加的修饰函数

    ~flyAnimal(){delete p;}
private:
    animal *p;
};

/*
*找一个信使去送信
* */
void sendMail(const flyAnimal & sender)
{
    cout << "I am " << sender.name() << endl;
    sender.run();
    sender.fly();
}

int main()
{
    flyAnimal sender(new eagle);    //用eagle做信使
    sendMail(sender);
    sender.setAnimal(new dove);         //动态改变信使
    sendMail(sender);
    sender.setAnimal(new birdmen);       //会飞的不一定是天使,还有鸟人
    sendMail(sender);
}

运行结果:
I am eagle
I am runing!
I am flying!

I am dove
I am runing!
I am flying!

I am birdmen
I am runing!
I am flying!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值