zoukankan      html  css  js  c++  java
  • 【设计模式】代理模式

    1、定义

    1.1 标准定义

      Provide a surrogate or placeholder for another object to control access to it.( 为其他对象提供一种代理以控制对这个对象的访问。 )

    1.2 通用类图

      代理模式也叫做委托模式, 它是一项基本设计技巧。 许多其他的模式, 如状态模式、 策略模式、 访问者模式本质上是在更特殊的场合采用了委托模式, 而且在日常的应用中, 代理模式可以提供非常好的访问控制。

      ● Subject抽象主题角色
      抽象主题类可以是抽象类也可以是接口, 是一个最普通的业务类型定义, 无特殊要求。

      ● RealSubject具体主题角色
      也叫做被委托角色、 被代理角色。 它才是冤大头, 是业务逻辑的具体执行者。

      ● Proxy代理主题角色
      也叫做委托类、 代理类。 它负责对真实角色的应用, 把所有抽象主题类定义的方法限制委托给真实主题角色实现, 并且在真实主题角色处理完毕前后做预处理和善后处理工作。

    1.3 代理种类

      远程(Remote)代理:为一个位于不同的地址空间的对象提供一个局域代表对象。这个不同的地址空间可以是在本机器中,也可是在另一台机器中。远程代理又叫做大使(Ambassador)。 也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。

      虚拟(Virtual)代理:根据需要创建一个资源消耗较大的对象,使得此对象只在需要时才会被真正创建。是根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象。  

      Copy-on-Write代理:虚拟代理的一种。把复制(克隆)拖延到只有在客户端需要时,才真正采取行动。

      保护(Protect or Access)代理:控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。 用来控制真实对象访问时的权限。一般用于对象应该有不同的访问权限的时候。

      Cache代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。 防火墙(Firewall)代理:保护目标,不让恶意用户接近。 同步化(Synchronization)代理:使几个用户能够同时使用一个对象而没有冲突。

      智能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来等。 是指当调用真实的对象时,代理处理另外一些事。如计算真实对象的引用次数,这样当该对象没有引用时,可以自动释放它;或当第一次引用一个持久对象时,将它装入内存;或在访问一个实际对象前,检查是否已经锁定它,以确保其他对象不能改变它。它们都是通过代理在访问一个对象时附加一些内务处理。

      在所有种类的代理模式中,虚拟(Virtual)代理、远程(Remote)代理、智能引用代理(Smart Reference Proxy)和保护(Protect or Access)代理是最为常见的代理模式。

    2、实现

    2.1 类图

      Subject:声明了真实主题和代理主题的共同接口,这样一来在任何使用真实主题的地方都可以使用代理主题。

      Proxy:代理主题角色内部含有对真是主题的引用,从而可以在任何时候操作真实主题对象;代理主题角色提供一个与真实主题角色相同的接口,以便可以在任何时候都可以替代真实主体;控制真实主题的应用,负责在需要的时候创建真实主题对象(和删除真实主题对象);代理角色通常在将客户端调用传递给真实的主题之前或之后,都要执行某个操作,而不是单纯的将调用传递给真实主题对象。

      ConcreteSubject:定义了代理角色所代表的真实对象。

    2.2 代码

    2.2.1 代理类

    //Proxy.h
    #ifndef _PROXY_H_
    #define _PROXY_H_
    
    // 定义了Proxy和ConcreteSubject的公有接口,
    // 这样就可以在任何需要使用到ConcreteSubject的地方都使用Proxy.
    class Subject
    {
    public:
        virtual ~Subject();
        virtual void Request()=0;
    protected:
        Subject();
    };
    
    class ConcreteSubject : public Subject
    {
    public:
        ConcreteSubject();
        ~ConcreteSubject();
        virtual void Request();
    };
    
    //定义代理类
    class Proxy : public Subject
    {
    public:
        Proxy();
        ~Proxy();
        void DoSomething1();
        virtual void Request();
        void DoSomething2();
    private:
        Subject* _subject;
    };
    #endif
    //Proxy.cpp
    #include "Proxy.h"
    #include "iostream"
    
    using namespace std;
    
    Subject::Subject(){}
    
    Subject::~Subject(){}
    
    ConcreteSubject::ConcreteSubject(){}
    
    ConcreteSubject::~ConcreteSubject(){}
    
    void ConcreteSubject::Request()
    {
        cout << "ConcreteSubject::Request" << endl;
    }
    
    Proxy::Proxy() : _subject(NULL){}
    
    Proxy::~Proxy(){}
    
    void Proxy::DoSomething1()
    {
        cout << "Proxy::DoSomething1" << endl;
    }
    
    void Proxy::DoSomething2()
    {
        cout << "Proxy::DoSomething2" << endl;
    }
    
    void Proxy::Request()
    {
        if(NULL == this->_subject)
        {
            this->_subject = new ConcreteSubject();
        }
    
        this->DoSomething1();//表示额外附加的操作
    
        this->_subject->Request();//代理的实体类操作
    
        this->DoSomething2();//表示额外附加的操作
    }

    2.2.2 调用

    // Main.cpp
    #include "Proxy.h"
    
    int main()
    {
        Proxy* proxy = new Proxy();
        proxy->Request();
    
        return 0;
    }

    3、优点

      ● 职责清晰
      真实的角色就是实现实际的业务逻辑, 不用关心其他非本职责的事务, 通过后期的代理完成一件事务, 附带的结果就是编程简洁清晰。

      ● 高扩展性
      具体主题角色是随时都会发生变化的, 只要它实现了接口, 甭管它如何变化, 都逃不脱如来佛的手掌( 接口) , 那我们的代理类完全就可以在不做任何修改的情况下使用。

      ● 智能化
      这在我们以上的讲解中还没有体现出来, 不过在我们以下的动态代理章节中你就会看到代理的智能化有兴趣的读者也可以看看Struts是如何把表单元素映射到对象上的。

    4、扩展

      强制代理

      调用者直接调用真实角色,而不关心代理是否存在,其代理的产生有真实角色决定。——强制要求,你必须通过真实角色查找到代理角色,否则不能访问

      实现方案:

      在真实角色中定义自己的代理者。每个流程的执行都首先判断是否有代理存在,否则提示无法访问在代理角色中,代理的代理返回this;

  • 相关阅读:
    关于研发核心团队建设的一些思考
    无法打开物理文件xxx.mdf操作系统错误 5:“5(拒绝访问。)” (Microsoft SQL Server,错误: 5120)的解决方法
    自适应网页设计(Responsive Web Design)
    css浮动与绝对定位小记
    WEB进度条控件
    GitHub上整理的一些工具
    雾里看花般的迷茫--货运APP
    揭秘史上最完美一步到位的搭建Andoriod开发环境
    我是如何在SQLServer中处理每天四亿三千万记录的
    货运APP产品魔力=卓越功能×情感诉求
  • 原文地址:https://www.cnblogs.com/ChinaHook/p/7236992.html
Copyright © 2011-2022 走看看