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

装饰模式:

动态地给对象添加一些相关的职责。装饰模式相比与添加子类提供了一种更加灵活的方式。

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;
}

执行结果如下:

时间: 2024-12-23 01:51:05

设计模式之三:装饰模式(Decorator)的相关文章

设计模式 笔记 装饰模式 Decorator

//---------------------------15/04/17---------------------------- //Decorator 装饰模式----对象结构型模式 /* 1:意图: 动态地给一个对象添加额外的职业,就增加功能来说,Decorator模式相比生成子类更为灵活. 2:别名: 包装器(Wrapper) 3:动机: 4:适用性: 1>在不影响其他对象的情况下,以动态.透明的方式给单个对象添加职责. 2>处理那些可以撤销的职责. 3>当不能采用生成子类的方法

【设计模式】—— 装饰模式Decorator

前言:[模式总览]——————————by xingoo 模式意图 在不改变原来类的情况下,进行扩展. 动态的给对象增加一个业务功能,就功能来说,比生成子类更方便. 应用场景 1 在不生成子类的情况下,为对象动态的添加某些操作. 2 处理一些可以撤销的职责. 3 当不能使用生成子类来扩充时. 模式结构 Component 外部接口,用于定义外部调用的形式.提供默认的处理方法. interface Component{ public void operation(); } ConcreteComp

设计模式之装饰模式 Decorator

代码实现 public interface ICar { void move(); } 抽象构建角色 //具体构件角色(真实对象,被装饰角色) class Car implements ICar{ @Override public void move() { System.out.println("陆地上跑"); } } 具体构建角色 //装饰角色 class SuperCar implements ICar{ private ICar car; public SuperCar(ICa

JAVA设计模式之 装饰模式【Decorator Pattern】

一.概述 动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活.装饰模式是一种对象结构型模式.装饰模式是一种用于替代继承的技术,使用对象之间的关联关系取代类之间的继承关系.在装饰模式中引入了装饰类,在装饰类中既可以调用待装饰的原有类的方法,还可以增加新的方法,以扩充原有类的功能. 二.适用场景 装饰原有对象.在不改变原有对象的情况下扩展增强新功能/新特征..当不能采用继承的方式对系统进行扩展或者采用继承不利于系统扩展和维护时可以使用装饰模式. 三.UML类图 四

设计模式--装饰模式(Decorator)

装饰模式(Decorator) : 动态的给一个对象加入一些额外的职能,就添加功能来说,装饰模式比生成子类更为灵活. 实例: ConcreteComponent:让Decorator对象为自己加入功能.有时候使用ConcreteComponent的派生类提供核心功能.在这样的情况就是用ConcreteComponent替代了Component的功能,并且装饰者是继承于ConcreteComponent的子类. Component:定义ConcreteComponent和Decorator类要实现

设计模式之装饰模式20170726

结构型设计模式之装饰模式: 一.含义 动态地给一个对象添加一些额外的职责.就增加功能来说,装饰模式相比生成子类更为灵活. 通俗来讲,装饰模式是对类的功能进行加强或减弱. 二.代码说明 1.主要有两个角色 1)构件 最核心.最原始.最基本的对象,也就是要装饰的对象. 2)装饰角色 把最核心.最原始.最基本的东西装饰成其他东西 2.在用C实现过程中也是参考这种思想,以修饰成绩单举例,具体实现如下: 1)装饰模式使用场景: 1 /***********************************

设计模式之装饰模式 c++实现和详细分析

Decorator模式(别名Wrapper):动态将职责附加到对象上,若要扩展功能,装饰者提供了比继承更具弹性的代替方案. 它使功能具有动态性 已经开发完毕的对象,后期由于业务需要,对旧的对象需要扩展特别多的功能,这时候使用给对象动态地添加新的状态或者行为(即装饰模式)方法,而不是使用子类静态继承. 引入装饰模式的原因  : 由于若有很多个功能,这么多功能 可能会出现各种组合,而每个组合都要对应一个类,这是指数级的类的数量增长(因为我们要扩展不应直接修改类,所以采取继承 而不是改变原有类)  

【设计模式】——装饰模式

装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活. 装饰模式结构图: Component是定义一个对象接口,可以给这些对象动态地添加职责.ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责.Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的.至于ConcreteDecorator就是具体

设计模式笔记——装饰模式

装饰模式 装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活. 1.装饰模式的特点 (1)装饰对象和真实对象有相同的接口.这样客户端对象就能以和真实对象相同的方式和装饰对象交互. (2)装饰对象包含一个真实对象的引用(reference) (3)装饰对象接受所有来自客户端的请求.它把这些请求转发给真实的对象. (4)装饰对象可以在转发这些请求以前或以后增加一些附加功能.这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功

学习大话设计模式06_装饰模式

装饰模式(Decorator): 动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活. 1 /** 2 * Component 是定义一个对象接口,可以给这些对象动态地添加职责 3 * @author Monica 4 * 5 */ 6 public abstract class Component { 7 public abstract void Operation(); 8 } 9 10 11 /** 12 * ConcreteComponent 是定义了一个具体