[学习笔记]设计模式之Proxy

为方便读者,本文已添加至索引:html

写在前面

“魔镜啊魔镜,谁是这个世界上最美丽的人?” 每到晚上,女王都会问魔镜相同的问题(见Decorator模式)。这是她还曾身为女巫时留下的习惯。尽管要提及这个心里邪恶的女巫,将会有一大堆故事,但咱们今天要讨论的主角,倒是这面神奇的镜子。关于魔镜的来历,谁都不是很清楚。就连这个世界的创造者魔导士(见Builder模式)也对它的存在感到好奇。魔镜可以回应主人的诉求,回答主人所提出的问题,并透过镜子来提示答案相关的信息。咱们能够经过时の魔导士的研究手札来依稀了解下这个神秘的魔法造物。程序员

“这面魔镜能够显现出我所创造的这个世界中任何的物体,这颇有趣。”设计模式

“……可是它彷佛也仅仅是提供了一种受限制的访问对象的方式,由于我不能经过它直接接触到对象自己。”函数

“……它也仅在我须要的时候才会显示出对应的物体,我相信它并不是从诞生之时就存储好了世界上全部物体的影像。”学习

“……魔镜在显示答案时更像是一种采用了Proxy模式的造物优化

是的,他提到了Proxy(代理),一种设计模式。在继续深刻研究魔镜以前,咱们先来了解下Proxy的大体内容。ui

要点梳理

  • 目的分类
    • 对象结构型模式
  • 范围准则
    • 对象(该模式处理对象间的关系,这些关系在运行时刻是能够变化的,更具动态性)
  • 主要功能
    • 为其余对象提供一种代理以控制对这个对象的访问
  • 适用状况
    • 在须要用比较通用和复杂的对象指针代替简单的指针的时候,使用Proxy。
    • 远程代理(Remote Proxy):为一个对象在不一样的地址空间提供局部表明
    • 虚代理(Virtual Proxy):根据须要建立开销很大的对象
    • 保护代理(Protection Proxy):控制对原始对象的访问
    • 智能指引(Smart Reference):取代了简单的指针,它在访问对象时执行一些附加操做。好比:对指向实际对象的引用计数,这样当该对象没有引用时,能够自动释放它;在访问一个实际对象前,检查是否已经锁定了它,以确保其余对象不能改变它等等。
  • 参与部分
    • Proxy:保存一个引用使得代理能够访问实体;提供一个与Subject的接口相同的接口,用来替代实体;控制对实体的存取,并可能负责建立和删除它;
    • Subject:定义RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方均可以使用Proxy
    • RealSubject:定义Proxy所表明的实体
  • 协做过程
    • 代理根据其种类,在适当的时候向RealSubject转发请求。
  • UML图例

示例分析 - 无所不知的魔镜

 

 

 

 

 

 

 

为了更加深刻地了解魔镜,咱们先回顾一个知识点:在Decorator模式笔记中,咱们了解到一个全部可见物体的抽象类VisualObject。从镜子之中,咱们能够看到某个对象的影像Image
spa

1 class Image : public VisualObject {
2 public:
3     Image(string name);     // load an image.
4     virtual ~Image();
5     
6     virtual void show();
7 }

然而透过魔镜,咱们能够看到任何想看东西的Image。如前文所述,不可能让魔镜在一开始就把全部的Image都实例化。(换成咱们程序员的思惟,就是会形成存储开销过于巨大),怎么办?Proxy模式给出了一种解决策略。让咱们看看所谓的ImageProxyMagic吧:设计

 1 class ImageProxyMagic : public VisualObject {
 2 public:
 3     ImageProxyMagic(string name);       // Just save the name.
 4     virtual ~Image();
 5     
 6     virtual void show();
 7 protected:
 8     Image* getImage();
 9 private:
10     string _name;
11     Image* _image;
12 }

诶,有没有发现它对外的接口和Image相同?是的,这样一来咱们就能够像操做Image同样,操做ImageProxyMagic了。可是具体它又作了什么?看看代码吧:代理

 1 ImageProxyMagic::ImageProxyMagic(string name) {
 2     _name = name;
 3     _image = 0;
 4 }
 5 
 6 Image* ImageProxyMagic::getImage() {
 7     if (!_image) {
 8         _image = new Image(_name);
 9     }
10     return _image;
11 }
12 
13 void ImageProxyMagic::show() {
14     getImage()->show();
15 }

注意到,构造函数存储了Image的名字,而将Image的装载过程延缓到getImage函数当中。于是,只有在某个Image真正须要show出来的时候,它才会被装载。ImageProxyMagic将show命令转发给Image处理。

尽管如此,咱们仍是不了解魔镜为何会知道问题的答案,咱们仅仅看到的它在展现答案时候的一个可能处理方式。咱们不由想对它提出这样一个问题:

“魔镜啊魔镜,你为何无所不知?”

特色总结

使用Proxy模式在访问对象时引入了必定程度的间接性。根据代理的类型,附加的间接性也有多种用途:

  1. Remote Proxy能够隐藏一个对象存在于不一样地址空间的事实。
  2. Virtual Proxy能够进行最优化,例如根据要求建立对象。
  3. Protectoin Proxy和Smart Reference都容许在访问一个对象时有一些附加的内务处理。

Proxy模式并不老是须要知道实体的类型。若是Proxy类可以彻底经过一个抽象接口处理它的实体,则无须为每个RealSubject类都生成一个Proxy类;但若是Proxy要实例化RealSubject的话,(好比咱们的例子中)那它必须知道具体的类。

写在最后

今天的笔记就到这里了,欢迎你们批评指正!若是以为能够的话,好文推荐一下,我会很是感谢的!

相关文章
相关标签/搜索