设计模式(12) 代理模式(PROXY)(一)

2014-11-24 02:45:36 · 作者: · 浏览: 2
问题聚焦: 这个模式是对象结构型模式的最后一个。学习完就可以进入下一种类型的模式了。 代理模式的主要目的:控制对某个对象的访问(如通过拒绝某些访问实现访问权限的控制,或进行加载等耗时操作的优化)。
意图: 为其他对象提供一种代理以控制对这个对象的访问。
别名: Surrogate
动机: 原因:为了只有在我们确实需要这个对象时才对它进行创建和初始化,因此对一个对象进行访问控制。 Demo:文档编辑器 需求:可以在文档中嵌入图形对象 挑战:有些图形对象的创建开销很大,但是打开文档必须很迅速,因此我们再打开文档时应避免一次性创建所有开销很大的对象。因此,并非所有这些文档中都同时可见,所以也没有必要同时创建这些对象。 方案:对于一个开销很大的对象,应该根据需要进行创建,当一个图像变为可见时,会产生这样的需求。这时,使用一个图像Proxy替代那个真正的图像,在需要的时候负责实例化这个图像对象。 \ \ 只有当文档编辑器激活图像代理的Draw操作以显示这个图像的时候,图像Proxy才创建真正的图像。 实现:
  • 文件名作为对实际对象的引用。
  • 代理存储了图像的尺寸(extent)
  • 文档编辑器通过抽象的Graphic类定义的接口访问嵌入的图像。ImageProxy是图像代理类。
  • ImageProxy保存了文件名作为指向磁盘上的图像文件的指针,该文件名作为一个参数传递给ImageProxy
  • ImageProxy还存储了这个图像的边框以及对真正的Image实例的指引,直到代理实例化真正图像时,这个指引才有效。
  • ImageProxy操作只有在图像被实例化后,才向它传递请求。 类图: \\
    适用性: 通常,在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用Proxy。 下面是一些可以使用Proxy模式的常见情况:
    • 远程代理:为一个对象在不同的地址空间提供局部代理
    • 虚代理:根据需要创建开销很大的对象,在上一节提到的ImageProxy就是这样一种代理的例子。
    • 保护代理:控制对原始对象的访问。用于对象应该有不同的访问权限的时候。
    • 智能指引:取代了简单的指针,它在访问对象时执行一些附加操作(引用计数,装入内存,加锁)。 结构: \
      \ 在运行时刻一种可能的代理结构的对象图如下所示:\ \


      参与者:
      • Proxy(ImageProxy):
        • 保存一个引用使得代理可以访问实体。
        • 提供一个与Subject的接口相同的接口,这样代理就可以用来替代实体
        • 控制对实体的存取,并可能负责创建和删除它
        • Subject(Graphic):
          • 定义RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy
          • RealSubject(Image):
            • 定义Proxy所代表的实体 协作: 代理根据其种类,在适当的时候向RealSubject转发请求。
              效果: Proxy模式在访问对象时,引入了一定程度的间歇性(一个中间层),在这个中间层中,可以做一些附加动作或者优化。 CZ http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcHktb24td3JpdGXTxbuvo7q21NPDu6fS/rLYo6y3osn61NrW0LzksuO1xNPFu6+howogICAg08W7r7OhvrCjur+9sbTSu7j2xdO087b4uLTU07XEttTP86Osv6rP+rrctPOjrMjnufvV4rj2v72xtLj5sb7Du9PQsbvQ3rjEo6zEx8O01eLQqb+qz/q+zcO709Cx2NKqoaMKICAgILe9sLijutPDUHJveHm21M/z0dOz2dXi0ru/vbG0uf2zzKOsztLDx7/J0tS1sda709DV4rj2ttTP87G70N64xLXEyrG68rLFttTL/L340NC/vbG0oaMKICAgIMq1z9ajutTavfjQ0GMtby1308W7r8qxo6yx2NDrttTKtczlvMzQ+MWh0v3Tw7zGyv2jrLWx0v3Tw8r9xL/OqsHjyrGjrMq1zOW9q7G7yb6z/aGjCiAgICDQp7n7o7q/ydLUtPO3+bbItcS9tbXNv72xtMXTtPPKtczlyrG1xL+qz/oKPGJyPgoKyrXP1qO6ClByb3h5v8nS1MD708PSu8/C0rvQqdPv0dTM2NDUo7oKCjx1bD4KPGxpPtbY1NhDJiM0MzsmIzQzO9bQtcS05sih1MvL47f7o7q9q7T6wO221M/z1/fOqsq1vMq21M/ztcTSu7j21rjV68q508OjqNbY1NgtPrrNKrLZ1/e3+6OpPGxpPlByb3h5sqKyu9fcysfQ6NKq1qq1wMq1zOW1xMDg0M2jusj0UHJveHnA4MTcubvN6sirzai5/dK7uPaz6c/zvdO/2rSmwO3L/LXEyrXM5aOs1PLO3tDozqrDv9K7uPbKtbzKttTP88DgtrzJ+rPJ0ru49rT6wO3A4KGjuMNQcm94eb/J0tTNs9K7tKbA7cv509C1xMq1vMq21M/zoaO1q8rHyOe5+7T6wO221M/z0OjSqsq1wP27r8q1vMq21M/zo6zEx8O0y/yx2NDr1qq1wL7fzOW1xMDgoaMKCjxicj4KCgo8aHI+CrT6wO3KvsD9o7oK0tTJz8PmzOG1vbXEzsSxvrHgvK3G986qwP2jrMq1z9bQ6bT6wO2jugpHcmFwaGljwODOqs280M621M/ztqjS5dK7uPa907/aCjxwcmUgY2xhc3M9"brush:java;">class Graphic { public: virtual ~Graphic(); virtual void Draw(const Point& at) = 0; virtual void HandleMouse( Event& event) = 0; virtual const Point& GetExtent() = 0; virtual void Load(istream& from) = 0; virtual void Save(ostream& to) = 0; protected: Graphic(); }; // Image类实现了Graphic接口用来显示图像文件的接口。 // 同时,实现了Handlemouse操作,使得用户可以交互第调整图像的尺寸。 class Image : public Graphic { public: Image(const char* file); virtual void Draw(const Point& at); virtual void HandleMouse( Event& event); virtual const Point& GetExtent(); virtual void Load(istream& from); virtual void Save(ostream& to); protected: // .... } // ImageProxy和Image具有相同的接口 class ImagePr