zoukankan      html  css  js  c++  java
  • 设计模式初探3——装饰者模式(Decorator Pattern)

    装饰者模式:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。


    适用范围:

    1. 须要扩展一个类的功能。或给一个类加入附加职责。
    2. 须要动态的给一个对象加入功能,这些功能能够再动态的撤销。
    3. 须要添加由一些基本功能的排列组合而产生的很大量的功能。从而使继承关系变的不现实。
    4. 当不能採用生成子类的方法进行扩充时。

    一种情况是,可能有大量独立的扩展。为支持每一种组合将产生大量的子类。使得子类数目呈爆炸性增长。

    还有一种情况可能是由于类定义被隐藏,或类定义不能用于生成子类。


    UML图:


    測试代码:
    我们创建一个Toy抽象类,然后来生产不同的玩具。并为它加上各种功能。
    #include <iostream>
    #include <string>
    using namespace std;
    
    class Toy {
    public:
        virtual string getDescription() = 0;
    };

    我们先生产一个玩具鸭,它还不太像一仅仅鸭子,而且不能发声:
    class Duck : public Toy {
    public:
        string getDescription(){ return "I'm a simple Toy-Duck. "; }
    }; 

    接着是装饰类的基类,它包括Toy基类的指针。以便訪问到我们的玩具鸭:
    class Decorator : public Toy {
    public:
        Decorator(Toy* t) : toy(t){}
    protected:
        Toy* toy;
    };

    创建形状装饰者和发声装饰者:
    class ShapeDecorator : public Decorator {
    public:
        ShapeDecorator(Toy* t) : Decorator(t){}
        string getDescription() {
            return toy->getDescription.append("Now I have new shape. ");
        }
    };

    class SoundDecorator : public Decorator {
    public:
        SoundDecorator(Toy* t) : Decorator(t){}
        string getDescription() {
            return toy->getDescription.append("Now I can quack. ");
        }
    };

    好了,我们在main函数中測试一下:
    int main()    
    {    
        Toy *toy = new Duck();
        cout << toy->getDescription();
    
        toy = new ShapeDecorator(toy);
        cout << toy->getDescription();
        
        toy = new SoundDecorator(toy);
        cout << toy->getDescription();   
        return 0;    
    } 

    让我们再关注一条十分重要的设计原则:
    对扩展开放,对改动关闭。

  • 相关阅读:
    线段树(segment tree)
    外排序
    【机器学习】如何成为当下合格的算法工程师
    Result Maps collection already contains value for
    负向零宽断言
    正则匹配中 ^ $ 和  的区别
    jq异步上传文件(转载)
    js触发按钮点击事件
    ./ ,../ , 以及/的区别
    eclipse遇到不会部署的情况
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5059115.html
Copyright © 2011-2022 走看看