zoukankan      html  css  js  c++  java
  • 【设计模式】 模式PK:代理模式VS装饰模式

    1、概述

      对于两个模式,首先要说的是,装饰模式就是代理模式的一个特殊应用,两者的共同点是都具有相同的接口,不同点则是代理模式着重对代理过程的控制,而装饰模式则是对类的功能进行加强或减弱,它着重类的功能变化,我们举例来说明它们的区别。

    2、代理模式

      一个著名的短跑运动员有自己的代理人。如果你很仰慕他,你找运动员说“你跑个我看看”,运动员肯定不搭理你,不过你找到他的代理人就不一样了,你可能和代理人比较熟,可以称兄道弟,这个忙代理人还是可以帮的,于是代理人同意让你欣赏运动员的练习赛,那么你的目的就达成了。

    2.1 类图

      这是一个套用代理模式的简单应用,非常简单。一个对象,然后再是自己的代理。

    2.2 代码

    2.2.1 抽象主题类

    class CIRunner
    {
    public :
        CIRunner (){};
        ~ CIRunner (){};
        virtual void mvRun() = 0;
    };

    2.2.2 短跑运动员

      一个具体的短跑运动员跑步是很潇洒的。

    class CRunner :public CIRunner
    {
    public:
        CRunner(){};
        ~CRunner(){};
        void mvRun(){ cout << "运动员跑步: 动作很潇洒" << endl; };
    };

    2.2.3 代理人

      看看现在的明星运动员,一般都有自己的代理人,要么是专职的,要么就是自己的教练兼职,那我们来看看代理人的职责。

    class CRunnerAgent : public CIRunner
    {
    public:
        CRunnerAgent(CIRunner *opRunner) { mopRunner = opRunner; }
        ~CRunnerAgent(){}
        void mvRun() { mopRunner->mvRun(); }
    private:
        CIRunner *mopRunner;
    };

    2.2.4 调用

      我们只是定义了一个代理人,并没有明确定义是哪一个运动员的代理,需要在运行时指定被代理者,对于主题类的行为是否可以发生,代理类有绝对的控制权。

    int main()
    {
        //定义一个短跑运动员
        CIRunner *op_runner = new CRunner();
    
        //定义的代理人
        CIRunner *op_agent = new CRunnerAgent(op_runner);
    
        //要求运动员跑步
        cout << "====客人找到运动员的代理要求其去跑步===" << endl;
        op_agent->mvRun();
    
        return 0;
    }

    2.2.5 运行结果

    3、装饰模式

    3.1 类图

      如果使用装饰模式,我们该怎么实现这个过程呢?装饰模式是对类功能的加强,怎么加强呢?增强跑步速度!在屁股后面安装一个喷气动力装置,类似火箭的喷气装置,那速度变得很快,《蜘蛛侠》中的那个反面角色不就是这样的吗?好,我们来看类图。

      很惊讶是吧?这个代理模式完全一样的类图。是的,完全一样!不过其实现的意图却不同。

    3.2 代码

      我们来看代码,CIRunner和CRunner与代理模式相同,在此不再赘述。

    3.2.1 装饰类

    class CRunnerWithJet : public CIRunner
    {
    public:
        CRunnerWithJet(CIRunner *opRunner){ mopRunner = opRunner; };
        ~CRunnerWithJet(){};
    
        void mvRun()
        {
            cout << "加快运动员的速度: 为运动员增加喷气装置" << endl;
            mopRunner->mvRun();
        }
    
    private:
        CIRunner *mopRunner;
    };

      这和代理模式中的代理类也是非常相似的,只是装饰类对类的行为没有决定权,只有增强作用,也就是说它不决定被代理的方法是否执行,它只是再次增加被代理的功能。

    3.2.2 场景调用

    int main()
    {
        //定义运动员
        CIRunner *op_runner = new CRunner();
        //对其功能加强
        op_runner = new CRunnerWithJet(op_runner);
        //看看它的跑步情况如何
        cout << "===增强后的运动员的功能===" << endl;
        op_runner->mvRun();
    
        return 0;
    }

    3.2.3 执行结果

      注意思考一下我们的程序,我们通过增加了一个装饰类,就完成了对原有类的功能增加,由一个普通的短跑运动员变成了带有喷气装置的超人运动员。

    4、总结

      通过例子,我们可以看出代理模式和装饰模式有非常相似的地方,甚至代码实现都非常相似,特别是装饰模式中省略抽象装饰角色后,两者代码基本上相同,但是还是有细微的差别。

      代理模式是把当前的行为或功能委托给其他对象执行,代理类负责接口限定:是否可以调用真实角色,以及是否对发送到真实角色的消息进行变形处理,它不对被主题角色(也就是被代理类)的功能做任何处理,保证原汁原味的调用。

      装饰模式是在要保证接口不变的情况下加强类的功能,它保证的是被修饰的对象功能比原始对象丰富(当然,也可以减弱),但不做准入条件判断和准入参数过滤,如是否可以执行类的功能,过滤输入参数是否合规等,这不是装饰模式关心的。

  • 相关阅读:
    地图初步
    多线程技术 初步
    核心动画 CAAnimation 进阶
    CALayer 进阶
    Quartz 2D 初步
    UIView 面面观
    CABasicAnimation 基础
    CGAffineTransform 放射变换解析 即矩阵变换
    RunTime 入门
    对Viewcontroller在UINavigationController中入栈出栈的一点点理解
  • 原文地址:https://www.cnblogs.com/ChinaHook/p/7475197.html
Copyright © 2011-2022 走看看