码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-06-03 00:59:20      阅读:146      评论:0      收藏:0      [点我收藏+]

标签:设计模式   抓虾   

装饰模式:
动态地给对象添加一些相关的职责。装饰模式相比与添加子类提供了一种更加灵活的方式。
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;
}

执行结果如下:
技术分享

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

标签:设计模式   抓虾   

原文地址:http://blog.csdn.net/u012501459/article/details/46337349

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!