Proxy 代理对象结构模式

     Proxy 代理模式,为其它对象提供一种代理以控制这个对象的访问。客户代码与代理类打交道,而做实际工作的类隐藏在代理类背后。当调用代理类中的一个函数时,代理类仅转而去调用实现中相应的函数。

     在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用 Proxy 代理模式。Proxy 适用于以下情况:

1.远程代理(Remote Proxy)为一个对象在不同的地址空间提供局部代表。比如要操作一个网络上的一个对象(网络性能不好时,问题尤其突出),这时应该将这个问题交给代理去完成。

2.虚代理(Virtual Proxy)根据需要创建开销很大的对象,将这个创建的过程交给代理去完成。

3.保护代理(Protection Proxy)控制对原始对象的访问。保护代理用于对象应该有不同的访问权限的时候。

4.智能指引(Smart Reference)取代了简单的指针,它在访问对象时执行一些附加操作。主要用途包括:1)对指向实际对象的引用计数,这样当该对象没有引用时,可以自动释放它(也称智能指针 Smart Pointer)。2)当第一次引用一个持久对象时,将它装入内存。3)在访问一个实际对象前,检查是否已经锁定了它,以确保其它对象不能改变它。

Proxy 代理模式的通用结构如下:

Proxy

参与者:

Proxy:保存一个引用使得代理可以访问实体。若 RealSubject 和 Subject 的接口相同,Proxy 会引用 Subject。提供一个与 Subject 的接口相同的接口,这样代理就可以用来代替实体。控制对实体的存取,并可能负责创建和删除它。其它功能依赖于代理的类型:远程代理,负责对请求及其参数进行编码,并向不同地址空间中的实体发送已编码的请求。虚代理,可以缓冲实体的附加信息,以便延迟对它的访问。保护代理,检查调用者是否有实现一个请求所必需的访问权限。

Subject:定义 RealSubject 和 Proxy 的共用接口,这样就在任何使用 RealSubject 的地方都可以使用 Proxy。

RealSubject:定义 Proxy 所代表的实体。

Proxy 代理根据其种类,在适当的时候向 RealSubject 转发请求。

效果:Proxy 模式在访问对象时引入了一定程度的间接性。Remote Proxy 可以隐藏一个对象存在于不同地址空间的事实。Virtual Proxy 可以进行最优化,例如根据需要创建对象。Protection Proxy 和 Smart Reference 都允许在访问一个对象时有一些附加的内务处理。

Proxy 模式还可以对用户隐藏“写时拷贝:copy-on-wirte”的优化方式,该优化根据需要创建对象。在实现 copy-on-write 时必须对实体进行引用计数。拷贝代理仅会增加引用计数。只有当用户请求一个修改该实体的操作时,代理才会真正拷贝它。在这种情况下,代理还必须减少实体的引用计数。当引用的数目为零时,这个实体将被删除。Copy-on-Write 可以大幅度的降低拷贝庞大实体时的开销。

Proxy  代理模式示例代码:

   1:   
   2:  #pragma once
   3:  #include <iostream>
   4:   
   5:  // 定义了 Proxy 和 RealSubject 的公有接口,
   6:  // 这样就可以在任何需要使用到 RealSubject 的地方都使用 Proxy.
   7:  class Subject
   8:  {
   9:  public:
  10:      Subject(){}
  11:      virtual ~Subject(){}
  12:   
  13:      virtual void Request() = 0;
  14:  };
  15:   
  16:  // 真正使用的实体
  17:  class RealSubject : public Subject
  18:  {
  19:  public:
  20:      RealSubject()
  21:      {
  22:          std::cout << "Constructing a RealSubjectc." << std::endl;
  23:      }
  24:      virtual ~RealSubject(){}
  25:   
  26:      virtual void Request()
  27:      {
  28:          std::cout << "Request By RealSubject." << std::endl;
  29:      }
  30:  };
  31:   
  32:  // 代理类,含有一个指向RealSubject对象的指针
  33:  class Proxy : public Subject
  34:  {
  35:  public:
  36:      Proxy() : m_pRealSubject(NULL)
  37:      {
  38:          std::cout << "Constructing a Proxy." << std::endl;
  39:      }
  40:      virtual ~Proxy()
  41:      {
  42:          delete m_pRealSubject;
  43:          m_pRealSubject = NULL;
  44:      }
  45:   
  46:      virtual void Request()
  47:      {
  48:          // 需要使用RealSubject的时候才去初始化
  49:          if (NULL == m_pRealSubject)
  50:          {
  51:              std::cout << "Request By Proxy." << std::endl;
  52:              m_pRealSubject = new RealSubject();
  53:          }
  54:          m_pRealSubject->Request();
  55:      }
  56:   
  57:   
  58:  private:
  59:      RealSubject* m_pRealSubject;
  60:  };

//test

   1:   
   2:  #include "Proxy.h"
   3:   
   4:  int main()
   5:  {
   6:      Subject* pProxy = new Proxy();
   7:      pProxy->Request();
   8:   
   9:      delete pProxy;
  10:   
  11:      return 0;
  12:  }

设计模式一书给出的代码示例:

虚代理示例,根据需要创建大对象时使用

   1:  //虚代理示例:
   2:  class Image;
   3:  extern Image* LoadAnImageFile(const char*);
   4:   
   5:  //ImagePtr 相当于 Proxy
   6:  class ImagePtr
   7:  {
   8:  public:
   9:      ImagePtr(const char* imageFile) 
  10:          : _imageFile(imageFile), _image(0)
  11:      {    }
  12:      virtual ~ImagePtr();
  13:   
  14:      //重载 -> 和 * 运算符使用 LoadImage 将 _image 返回给它的调用者。
  15:      virtual Image* operator->()
  16:      {
  17:          return LoadImage();        /
  18:      }
  19:      virtual Image& operator*()
  20:      {
  21:          return *LoadImage();    //
  22:      }
  23:   
  24:  private:
  25:      Image* LoadImage()
  26:      {
  27:          if(_image = 0)
  28:              _image = LoadAnImageFile(_imageFile);
  29:          return _image;
  30:      }
  31:  private:
  32:      Image* _image;
  33:      const char* _imageFile;
  34:  };
  35:   
  36:  //该方法使你能够通过 ImagePtr 对象调用 Image 操作,而省去了把这些操作作为
  37:  //ImagePtr 接口的一部分的麻烦。
  38:  ImagePtr image = ImagePtr("anImageFileName");
  39:  image->Draw(Point(50,100));
  40:  //即 (image.operator->())->Draw(Point(50,100));
  41:  //请注意这里的 image 代理起到一个指针的作用,但并没有将它定义一个指向 Image 的指针。
  42:  //这意味着你不能把它当作一个真正的指向 Image 的指针来使用。因此在使用此方法时用户
  43:  //应区别对待 Image 对象和 ImagePtr 对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值