设计模式之装饰模式

介绍
  • 扩展类型可以通过继承来实现, 但很多时候我们需要为对象动态添加一些部件, 用继承实现的话可能会造成子类的膨胀, 而且也没有必要专门为一种对象设立一种类型, 比如现在有一个文本框类, 现在需要需要一个带滑动条的文本框 或是一中带按钮与滑动条的文本框, 显然由于需求的经常变化, 如果采用继承来提供这样的对象是不合理的, 采用装饰模式, 只要对文本框对象动态的添加上相应的部件即可.
适用
  • 在不影响其他对象的情况下, 以动态 透明的方式给单个对象添加职责;
  • 处理那些可以撤销对象职责的情况;
  • 当新添加类型不能或不宜采用子类的方法进行扩充, 如组合可能会产生大量独立的子类, 或应类型被隐藏或类定义不能产生子类的情况;
例子
  • 小明和小梦买了一套房Home, 现在他们想要装修大厅Parlor, 小明决定在电视背景墙上应该装上一面山水瓷画LandscapeBkgrdPts, 小梦想在天花板装上一漂亮的吊灯Chandelier, 装修好后过了几天, 小梦又想装一粉红色窗帘PinkCurtain, 小明想在大厅的角楼放上一盆栽potted, …..

分析

  • 显然例子中小两口想把房子装修的漂亮些, 会对大厅, 卧室进行各种装修, 添加各种部件, 甚至后面还会继续修改, 这样我们就不可能每次修改就把房子设计成一个新的类, 我们只需把房间Room抽象出来, 将客厅Hall, 卧室BeddingRoom继承房间, 再通过装修类Decoration来对这些对象进行装修, 而具体的装修方法则只是将Room对象进行一层层的包装;

这里写图片描述

代码


// 房间抽象类
class Room
{
public:
    virtual void Decoratting() = 0;
};
// 什么房间
class Hall : public Room
{
public:
    virtual void Decoratting()
    {
        cout<<"Decorate the Hall..."<<endl;
    }
};
class BedRoom : public Room
{
public:
    virtual void Decoratting()
    {
        cout<<"Decorate the bedroom..."<<endl;
    }
};
// 装饰类接口
class Decorator : public Room
{
public:
    Decorator(){};
    virtual void Decoratting()
    {
        if(mRoom)
            mRoom->Decoratting();
        cout<<"decorate the rooms!"<<endl;
    };
    void SetRoom(Room* room)
    {
        mRoom = room;
    }
private:
    Room* mRoom;
};
// 具体的装饰方法
class Parlor : public Decorator
{
public:
    Parlor(Room* r){SetRoom(r);};
    virtual void Decoratting()
    {
        Decorator::Decoratting();
        AddParlor();
        cout<<"---------------------------"<<endl;
    }
private:
    void AddParlor()
    {
        cout<<" add the parlor on the wall!"<<endl;
    }
};
class LandscapeBkgrdPts : public Decorator
{
public:
    LandscapeBkgrdPts(Room* r){SetRoom(r);};
    virtual void Decoratting()
    {
        Decorator::Decoratting();
        AddLdscpBkgrdPts();
        cout<<"---------------------------"<<endl;
    }
private:
    void AddLdscpBkgrdPts()
    {
        cout<<"add the landscape background painting"<<endl;
    }
};
class PinkCurtain : public Decorator
{
public:
    PinkCurtain(Room* r){SetRoom(r);};
    virtual void Decoratting()
    {
        Decorator::Decoratting();
        AddPinkCurtain();
        cout<<"---------------------------"<<endl;
    }
private:
    void AddPinkCurtain()
    {
        cout<<"add the pink curtain!"<<endl;
    }
};

结果

int main()
{
    Room* pHall = new Parlor(new PinkCurtain(new LandscapeBkgrdPts(new Hall)));
    pHall->Decoratting();
    return 0;
}

这里写图片描述

总结
  • 每一次添加部件都是通过Decorator父类指针来指向被包装对象;
  • 每添加一层包装, 就添加了一层统一虚函数接口Decoratting(), 当调用该函数时就会一层一层父类(里层包装对象)被调用!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值