设计模式——代理模式

来源:互联网 发布:mac地址里ig位 编辑:程序博客网 时间:2024/06/19 01:20

1. 概述

  代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问。是属于结构型模式。

2. 结构图

  下面是代理模式(Proxy)的结构图:

  • Proxy:保存一个引用使得代理可以访问实体。若RealSubject和Subject的接口相同,Proxy会引用Subject;提供一个与Subject的接口相同的接口,这样代理就可以来代替实体;控制对实体的存取,并可能负责创建和删除它。
  • Subject:定义RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy。
  • RealSubject:定义Proxy所代表的实体。
  代理根据其种类,在适当的时候向RealSubject转发请求。
  Proxy模式在访问对象时引入了一定程度的间接性。根据代理的类型,附加的间接性有很多种用途:
  1. 远程代理(Remote Proxy)可以隐藏一个对象存在于不同地址空间的事实。
  2. 虚代理(Virtual Proxy)可以进行最优化,例如根据要求创建对象。
  3. 保护代理(Protection Proxies)和智能引用(Smart Reference)都允许在访问一个对象时有一些附加的内务处理。
  Proxy模式还可以对用户隐藏另一种称之为copy-on-write的优化方式,该优化与根据需要创建对象有关。拷贝一个庞大而复杂的对象是一种开销很大的操作,如果这个拷贝根本没有被修改,那么这些开销就没必要。用代理延迟这一拷贝过程,我们可以保证只有当这个对象被修改的时候才对它进行拷贝。在实现copy-on-write时必须对实体进行引用计数。拷贝代理仅会增加引用计数。只有当用户请求一个修改该实体的操作时,代理才会真正的拷贝它。在这种情况下,代理还必须减少实体的引用计数。当引用计数为零,这个实体将被删除。

3. 实例分析

  对一个对象进行访问控制的一个原因是为了只有在我们确实需要这个对象时才对它进行创建和初始化。
  我们考虑一个可以在文档中嵌入图形对象的文档编辑器。有些图形对象的创建开销很大。但是打开文档必须很迅速,因此我们打开文档时应该避免一次性创建所有开销很大的对象。因为并非所有这些对象在文档中都同时可见,所以也没有必要同时创建这些对象。
  这一限制条件意味着,对于每一个开销很大的对象,应该根据需要进行创建,当一个图形变为可见时会产生这样的需要。但是在文档中我们用什么来替代这个图像呢?我们又如何才能隐藏根据需要创建图像这一事实,从而不会使得编辑器的实现复杂化呢?例如,这种优化不应该影响绘制和格式化的代码。
  问题的解决方案是使用另一个对象,即图像Proxy,替代那个真正的图像。Proxy可以代替一个图形对象,并且在需要时负责实例化这个图像对象。
  只有当文档编辑器激活图像代理的Draw操作以显示这个图像的时候,图像Proxy才创建真正的图像。Proxy直接将随后的请求转发给这个图像对象。因此在创建这个图像以后,它必须有一个指向这个图像的引用。
/**********************************************************************************Copyright(C),Your Company*FileName:  Graphic.h*Author:  Huangjh*Version:*Date:  2017-11-21*Description:  相当于结构图中的Subject角色——定义嵌入图形的访问接口*Others:**********************************************************************************/#ifndef _GRAPHIC_H#define _GRAPHIC_Hclass CGraphic{public:CGraphic() { }virtual ~CGraphic() { }virtual void Draw(void) = 0;};#endif//#ifndef _GRAPHIC_H
/**********************************************************************************Copyright(C),Your Company*FileName:  Image.h*Author:  Huangjh*Version:*Date:  2017-11-21*Description:  相当于结构图中的RealSubject角色——某个创建开销很大的图像对象*Others:**********************************************************************************/#ifndef _IMAGE_H#define _IMAGE_H#include <iostream>#include "Graphic.h"class CImage : public CGraphic{public:CImage() {std::cout << "某个图像对象,创建开销很大,速度慢" << std::endl;}~CImage() { }void Draw(void){std::cout << "绘制出这个开销很大的图像对象" << std::endl;}};#endif//#ifndef _IMAGE_H
/**********************************************************************************Copyright(C),Your Company*FileName:  ImageProxy.h*Author:  Huangjh*Version:*Date:  2017-11-21*Description:  相当于结构图中的Proxy角色——某个开销很大的图像代理*Others:**********************************************************************************/#ifndef _IMAGE_PROXY_H#define _IMAGE_PROXY_H#include <new>#include "Graphic.h"#include "Image.h"class CImageProxy:public CGraphic{public:CImageProxy():m_pImage(NULL){std::cout << "图像Proxy,替代那个真正的图像,创建很快" << std::endl;}~CImageProxy(){if (m_pImage)delete m_pImage;}void Draw(void){try{if (m_pImage == NULL)m_pImage = new CImage();}catch (std::bad_alloc &ex){std::cout << "Throw bad_alloc: " << ex.what() << std::endl;abort();}m_pImage->Draw();}private:CImage *m_pImage;};#endif//#ifndef _IMAGE_PROXY_H
/**********************************************************************************Copyright(C),Your Company*FileName:  main.cpp*Author:  Huangjh*Version:*Date:  2017-11-21*Description:  代理模式的测试用例*Others:**********************************************************************************/#include "Graphic.h"#include "ImageProxy.h"int main(void){//例如这里打开文档,文档里面有个开销很大的对象,该对象并不在文档开始可见,使用代理模式避免打开满的问题std::cout << "打开文档——创建图像Proxy" << std::endl;CGraphic *pImageProxy = new CImageProxy();//文档打开后,我们将浏览到该图像对象std::cout << "浏览到该对象——需要创建和绘制" << std::endl;pImageProxy->Draw();return 0;}
  运行结果如下所示:
打开文档——创建图像Proxy图像Proxy,替代那个真正的图像,创建很快浏览到该对象——需要创建和绘制某个图像对象,创建开销很大,速度慢绘制出这个开销很大的图像对象

4. 优缺点

4.1 优点

  • 代理模式能够协调调用者和被调用者吗,在一定程度上降低了系统的耦合度。
  • 远程代理是的客户端可以访问在远程机器上的对象,远程机器可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。
  • 虚拟代理通过使用一个小对象来代表一个大对象,可以减少系统资源的消耗,对系统进行优化并提高运行速度。
  • 保护代理可以控制对真实对象的使用权限。

4.2 缺点

  • 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
  • 实现代理模式需要额外的工作,有些代理秘书的实现比较复杂。

5. 适用性

  在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用Proxy模式。下面是一些可以使用Proxy模式常见的情况:
  1. 远程代理(Remote Proxy) 为一个对象在不同的地址空间提供局部代表。
  2. 虚代理(Virual Proxy) 根据需要创建开销很大的对象。
  3. 保护代理(Protection Proxy) 控制对原始对象的访问。保护代理用于对象应该有不同的访问权限的时候。
  4. 智能指引(Smart Reference) 取代了简单的指针,它在访问对象时执行一些附加操作。
  它(智能指引)的典型用途包括:
  • 对指向实际对象的引用计数,这样当该对象没有引用时,可以自动释放它。
  • 当第一次引用一个持久对象时,将它装入内存。
  • 在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。

6. 参考资料

  • 《大话设计模式》
  • 《设计模式——可复用的面向对象软件的基础》

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 老有白带涌出来怎么办 耳朵里塞了珠子怎么办 树脂发光字烧了怎么办 马蹄莲长得太高怎么办 百合球的芽断了怎么办 种的百合开败怎么办 盆栽百合花开完之后怎么办 土养百合花谢了怎么办 多肉叶子不饱满怎么办 冬天富贵竹叶子发黄怎么办水养 富贵竹叶子发黄怎么办水养 水养富贵竹有虫怎么办 水养的富贵竹叶子发黄怎么办 百合花水里的盐放多了怎么办 芦荟叶子发黄干瘪了怎么办 水插百合不开花怎么办 干百合冷水泡了怎么办 牡丹籽油过期了怎么办 ps画布建小了怎么办 腰突然疼的受不了了怎么办 微信里面打不开表格怎么办? 浏览器未正常加载相关控件怎么办 猫的眼睛发炎了怎么办 橡胶手机壳松了怎么办 橡胶手机壳小了怎么办 苹果手机下载不了软件了怎么办 苹果手机浏览器下载不了软件怎么办 小狗吃了硬的棉花怎么办 小狗吃了隔尿垫里的棉花怎么办 眼睫毛掉进眼睛里怎么办 爱掉头发怎么办吃什么 头皮屑多头发干燥脱发怎么办 剪了头发后悔了怎么办 2岁宝宝发际线高怎么办 脱发怎么办吃什么能长发 后面头发睡平了怎么办 鸟羽毛长得不好怎么办 吃激素药头发掉怎么办 吃了药头发掉怎么办 头皮痒头发掉的厉害怎么办 西昌学院被记过了怎么办?