zoukankan      html  css  js  c++  java
  • 【设计模式】装饰模式

    修饰模式是一种动态地往一个对象中加入新的行为的设计模式。继承是对现有类进行扩充,用来添加基类功能,该扩充动作是在编译期完毕。而修饰模式是对一个对象进行扩充。从而达到修饰的目的,该修饰动作是在执行期完毕。装饰模式的UML图例如以下:


    以下是一个用C++编写的关于描写叙述一个人的演示样例程序,并使用了装饰模式。

    #include <iostream>
    #include <string>
       
    using namespace std;
       
    // Component
    class Person {
    public:
        virtual void Describe() = 0;
        virtual ~Person()    // 存在继承关系,须要使用虚析构函数
        {}
    };
       
    // ConcreteComponent
    class Student : public Person {
    public:
        Student(const string &n) : name(n)
        {}
        // 重写虚函数
        void Describe()
        {
            cout << "Name : " << name << endl;
        }
    private:
        string name;
    };
       
    // Decorator
    class Decorator : public Person {
    public:
        Decorator(Person *p)
        {
            person = p;
        }
       
        void Describe()
        {
            person->Describe();  // 调用被修饰对象自身的方法
        }
     
    private:
        Person *person; // 保存须要被修饰的对象
    };
      
    // ConcreteDecorator
    class DecoratorAge : public Decorator {
    public:
        DecoratorAge(Person *p, int a) : Decorator(p), age(a)
        {}
       
        void Describe()
        {
            Decorator::Describe();
            cout << "Age : " << age << endl;  // 修饰
        }
    private:
        int age;
    };
      
    // ConcreteDecorator
    class DecoratorSex : public Decorator {
    public:
        DecoratorSex(Person *p, const string &s) : Decorator(p), sex(s)
        {}
       
        void Describe()
        {
            Decorator::Describe();
            cout << "Sex : " << sex << endl;  // 修饰
        }
    private:
        string sex;
    };
       
    int main()
    {
        Student s("Nestle");
           
        cout << "无修饰:" << endl;
        s.Describe();
        cout << endl;
       
        cout << "修饰年龄:" << endl;
        DecoratorAge decoratorAge(&s, 24);      // 修饰器
        decoratorAge.Describe();
        cout << endl;
       
        cout << "修饰性别:" << endl;
        DecoratorSex decoratorSex(&s, "man");   // 修饰器
        decoratorSex.Describe();
        cout << endl;
       
        cout << "同一时候修饰年龄和性别:" << endl;
        DecoratorSex decoratorAll(&decoratorAge, "man");    // 修饰器
        decoratorAll.Describe();
        cout << endl;
       
        system("pause");
        return 0;
    }

    执行结果:


    在这个样例中,我把人作为修饰对象,并从Person抽象类(在装饰模式中被称为Component)派生出一个Student非抽象类(在装饰模式中被称为ConcreteComponent)。

    该类中有一个描写叙述自己的成员函数Describe,但描写叙述的内容十分简单,所以须要使用装饰模式对描写叙述内容进行修饰扩充。接下来在从Person类派生出一个Decorator类,这个类是其他修饰器类的基类,也就是说。真正对Student对象进行修饰的类必须继承自Decorator类。在Decorator类中保存有被修饰对象的指针,我们须要用这个指针完毕被修饰对象自身的操作。我在这个样例中构建了两个详细的修饰类(在装饰模式中被称为ConcreteDecorator)。一个是修饰Student年龄的DecoratorAge类,还有一个是修饰Student性别的DecoratorSex类。它们运行完被修饰对象原有的操作后。就运行自己的修饰行为。分别输出年龄和性别,从而达到修饰目的。在用户代码中,实例化了一个Student对象和三个修饰器,修饰器可任意的对Student对象进行修饰。

    装饰模式的优点在于,对一个对象功能的扩充不须要在该对象所属类中加入代码。仅仅须要单独建立一个或几个类,用这些类来修饰对象。这样便有效地把类的核心职责和装饰功能分离开来。

    而且修饰方法很灵活,在上面的样例中,我们能够仅仅修饰年龄或对象或同一时候修饰。形成一个修饰链。

    參考:

    《大话设计模式》第6章

    维基百科

  • 相关阅读:
    OAuth2.0协议流程
    记多个微服务同时被kill分析
    记一次调用API遇到的问题
    win10安装mysql遇到的坑
    nagios
    rmp安装mysql5.6
    桥接模式-xshell连接虚拟机
    VMWare虚拟机-网络适配器
    ***时间目录***
    docker常用命令
  • 原文地址:https://www.cnblogs.com/clnchanpin/p/7286839.html
Copyright © 2011-2022 走看看