zoukankan      html  css  js  c++  java
  • 装饰器模式(Decorator)

    1、作用

    引入一个设计原则:类应该对扩展开发,对修改关闭。简单的说,就是允许我们的我们的类进行扩展,在不修改现有代码的情况  下,适应新的行为改变。

    当实现好的类有了新的需求,不考虑重用的话,会直接修改(现在写代码都这样,没有满足开闭原则的修改关闭原则),如果考虑代码的重用,以面向对象的设计思想,多数会想到使用继承,增加新添加的需求,但是如果需求很多,继承类的层次就很深,不方便维护和使用。使用装饰器模式,可以满足新加需求的功能,同时照顾的重用代码,并且避免继承的层次很深。

    对原有的输出进行处理得到需要的输出(修饰),而不是修改原点代码,来改变原来代码的输出。这个模式最能够用到编写的脚本上,扩展脚本的功能。

    2、实现方式

    假设要实现一个简单的打印功能,实用了一个抽象类AbsPrint定义了接口,同时实现了一个具体的打印类BasePrint类,完成打印的基本功能。

    但是后续需要添加新的打印需求,比如在打印内容的前后增加"*"和给打印内容加“()”。前面已经分析过,如果直接使用继承的方式,会导致类的层次很深,比利于后期维护,并且在设计模式中:Favor object composition over class inheritance,所以使用装饰器模式是一个比较好的方法(装饰类与原有类是一个关联关系),在不改变原有接口的情况下,添加新的功能,原有接口输出的内容进行处理。

    使用Decorator模式,要添加一个中间类:AbsDecorator,这个类唯一功能就是封装一个AbsPrint对象(有的像),从AbsDecorator扩展出两个装饰类,AddBrackets和AddStar类来实现新增的功能。

    装饰器可以嵌套使用(即使用AddBrackets又使用AddStart)

    3、C++代码

    print.h

    #include <iostream>
    
    #ifndef __PRINT__H__
    #define __PRINT__H__
    
    using namespace std;
    
    class AbsPrint {
        public:
            AbsPrint() = default;
            virtual ~AbsPrint() = default;
            virtual void print(const string &str) = 0;
    };
    
    class BasePrint : public AbsPrint {                     // 已有的功能,下面的都是新增的需求
        public:
            void print(const string &str) override {
                cout<<str;
            }
    };
    
    
    class AbsDecorator : public AbsPrint {                    // 这个类的唯一目的就是封装AbsPrint对象,这样可以避免每个装饰器类都加这个成员。
        public:
            AbsDecorator(AbsPrint *p) : p(p) {}
            ~AbsDecorator() { delete p; }
        protected:
            AbsPrint *p;
    };
    
    class AddBrackets : public AbsDecorator {                  // 添加换行符的装饰器
        public:
            AddBrackets(AbsPrint *p):AbsDecorator(p){}
            void print(const string &str) override {
                cout<<"(";
                p->print(str);
                cout<<")";
            }
    };
    
    
    class AddStar : public AbsDecorator {                       // 首尾添加*的装饰器
        public:
            AddStar(AbsPrint *p): AbsDecorator(p) {}
            void print(const string &str) override {
                cout<<"*";
                p->print(str);
                cout<<"*";
            }
    };
    
    #endif

    test.cc

    #include <iostream>
    #include "print.h"
    
    using namespace std;
    
    int main() {
        AbsPrint *p1 = new BasePrint;
        p1->print("hello world!");      // 直接使用基本的功能
        cout<<endl;
    
        AbsPrint *p2 = new AddStar(new BasePrint);
        p2->print("hello world!");      // 使用了添加"*"的装饰器
        cout<<endl;
    
        AbsPrint *p3 = new AddBrackets(new BasePrint);
        p3->print("hello world!");      // 使用了添加"()"的装饰器
        cout<<endl;
    
        AbsPrint *p4 = new AddBrackets(new AddStar(new BasePrint));
        p4->print("hello world!");      // 同时使用了加"*"和加"()"的装饰器
        cout<<endl;
    
        return 0;
    }

     输出:

  • 相关阅读:
    Clojure实现的简单短网址服务(Compojure、Ring、Korma库演示样例)
    android4.4系统解决“ERRORcouldn&#39;t find native method”方法
    JS window.open()属性
    网页视频播放器代码大全 + 21个为您的站点和博客提供的免费视频播放器
    理解Java的GC日志
    图像识别技术
    堆排序原理及算法实现(最大堆)
    什么是依赖注入
    Cocos2d-x3.1下实现相似iOS页面滑动指示圆点
    [Bootstrap] 6. Navigation
  • 原文地址:https://www.cnblogs.com/yuandonghua/p/11842519.html
Copyright © 2011-2022 走看看