设计模式之三:装饰模式(Decorator)

装饰模式允许动态地给对象增加新的职责,提供了比继承更灵活的扩展对象功能的方式。本文通过UML图解析了装饰模式的关键点,包括Decorator与Component的聚合和继承关系,并遵循里氏替换原则。同时,给出了一个图书馆资源的例子,展示了如何使用装饰模式为不同类型的资源添加可选特性。
摘要由CSDN通过智能技术生成

装饰模式:
动态地给对象添加一些相关的职责。装饰模式相比与添加子类提供了一种更加灵活的方式。
UML图如下所示:
这里写图片描述
感觉上图中关键的有这几点:

  1. Decorator与Component的聚合关系(即Decorator中存在一个Component类型的引用),由于这个聚合关系的存在,Decorator可以通过一个Component的引用调用Component的接口
  2. Decorator与Component的继承关系,这个关系不是很容易理解。但是在这里联想到继承的里氏代换原则(父类出现的地方都可以替换成子类),就好理解了。即Decorator类也可以作为上面第1点中的聚合的对象,这点才是装饰模式的关键所在。
  3. 上图的继承关系在现实世界中不是很好理解,但是它们符合面向对象中继承需要遵守的里氏替换原则,将这个原则带入来考虑这个设计模式很多地方就可以想通了。

主要包括:

  1. Component(LibraryItem):定义了一个为对象动态添加功能的接口
  2. ConcreteComponent(Book,Video):定义了能动态添加功能的对象
  3. Decorator(Decorator):操作了一个Component对象的引用
  4. ConcreteDecorator(Borrowable,Written):往Component(以及它的子类中)中添加功能

装饰模式的代码实现:

#include <stdlib.h>
#include <stdio.h>
#include <iostream>

class Component
{
    public:
        virtual void operation()=0;
};

class ConcreteComponent:public Component
{
    public:
        void operation()
        {
            std::cout<<"ConcreteCompont:operation()"<<std::endl;
        }
};

class Decorator:public Component
{
    public:
        void operation()
        {
            if(component!=NULL)
            {
                component->operation();
            }
        }
        void setComponent(Component * c)
        {
            component=c;
        }
    private:
        Component * component;
};

class ConcreteDecoratorA:public Decorator
{
    public:
        void operation()
        {
            Decorator::operation();
            std::cout<<"ConcreteDecoratorA::operation()"<<std::endl;
        }
};

class ConcreteDecoratorB:public Decorator
{
    public:
        void operation()
        {
            Decorator::operation();
            std::cout<<"ConcreteDecoratorB::operation()"<<std::endl;
        }
};

int main()
{
    std::cout<<"装饰模式测试"<<std::endl;
    ConcreteComponent *c=new ConcreteComponent();
    ConcreteDecoratorA *cda=new ConcreteDecoratorA();
    ConcreteDecoratorB *cdb=new ConcreteDecoratorB();
    cda->setComponent(c);
    cdb->setComponent(cda);

    std::cout<<"cda->operation() include:"<<std::endl;
    cda->operation();

    std::cout<<"--------------------"<<std::endl;

    std::cout<<"cdb->operation() include:"<<std::endl;
    cdb->operation();

    delete c;
    delete cda;
    delete cdb;
    return 0;
}

这里写图片描述
然后考虑一个具体的例子,即图书馆中的资源以及它们的一些特性,这些特性不是关键的并且可能有的时候需要有的时候又不需要,所以可以将它们不定义在各自的类中而通过装饰模式来实现。

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>

using namespace std;
/**
 *一个真实的例子:模拟一个图书馆中的的资源(书,视频),它们各自的特性(可借阅,可写入)
 *Component为LibraryItem
 *ConcreteComponent为Book,Video
 *Decorator为Decorator
 *ConcreteDecorator为Borrowable,Written
 */

class LibraryItem
{
    public:
                virtual void show()=0;
};

class Book:public LibraryItem
{
    public:
            Book()
            {

            }
            Book(string str):name(str)
            {

            }
            void show()
            {
                std::cout<<"book:"<<name<<std::endl;
            }
    private:
            string name;
};


class Video:public LibraryItem
{
    public:
            Video()
            {

            }
            Video(string str):name(str)
            {

            }
            void show()
            {
                std::cout<<"Video:"<<name<<std::endl;
            }
    private:
            string name;
};

class Decorator:public LibraryItem
{
    public:
            Decorator()
            {

            }
            Decorator(LibraryItem * item)
            {
                libraryItem=item;
            }
            void show()
            {
                if(libraryItem!=NULL)
                        libraryItem->show();
            }

    private:
            LibraryItem * libraryItem;

};

class Written:public Decorator
{
    public:
            Written()
            {

            }
            Written(LibraryItem* item):Decorator(item)
            {
            }
            void show()
            {
                Decorator::show();
                std::cout<<"written"<<std::endl;    
            }
};

class Borrowable:public Decorator
{
    public:
            Borrowable()
            {

            }
            Borrowable(LibraryItem* item):Decorator(item)
            {
            }
            void show()
            {
                Decorator::show();
                std::cout<<"borrowable"<<std::endl; 
            }
};

int main()
{
    std::cout<<"具体的装饰模式例子:"<<std::endl;
    std::cout<<"-----------------------"<<std::endl;
    Book *book=new Book("BigTalkDesignPattern");
    Borrowable* borrowableBook=new Borrowable(book);
    Written* writtenBook=new Written(borrowableBook);
    writtenBook->show();

    std::cout<<"-------------------------"<<std::endl;
    Video* video=new Video("Walking Death");
    Borrowable* borrowableVideo=new Borrowable(video);
    borrowableVideo->show();

    delete book;
    delete borrowableBook;
    delete writtenBook;
    delete video;
    delete borrowableVideo;



    return 0;
}

执行结果如下:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值