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

写在前面

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

“这面魔镜可以显现出我所创造的这个世界中任何的物体,这很有趣。”

“……但是它似乎也仅仅是提供了一种受限制的访问对象的方式,因为我不能通过它直接接触到对象本身。”

“……它也仅在我需要的时候才会显示出对应的物体,我相信它并非从诞生之时就存储好了世界上所有物体的影像。”

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

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

要点梳理

  • 目的分类

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

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

为了更加深入地了解魔镜,我们先回顾一个知识点:在Decorator模式笔记中,我们了解到一个所有可见物体的抽象类VisualObject。从镜子之中,我们可以看到某个对象的影像Image

 class Image : public VisualObject {
public:
Image(string name); // load an image.
virtual ~Image(); virtual void show();
}

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

 class ImageProxyMagic : public VisualObject {
public:
ImageProxyMagic(string name); // Just save the name.
virtual ~Image(); virtual void show();
protected:
Image* getImage();
private:
string _name;
Image* _image;
}

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

 ImageProxyMagic::ImageProxyMagic(string name) {
_name = name;
_image = ;
} Image* ImageProxyMagic::getImage() {
if (!_image) {
_image = new Image(_name);
}
return _image;
} void ImageProxyMagic::show() {
getImage()->show();
}

注意到,构造函数存储了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的话,(比如我们的例子中)那它必须知道具体的类。

写在最后

今天的笔记就到这里了,欢迎大家批评指正!如果觉得可以的话,好文推荐一下,我会非常感谢的!

[学习笔记]设计模式之Proxy的更多相关文章

  1. [学习笔记]设计模式之Abstract Factory

    写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 在上篇笔记Builder设计模式中,时の魔导士祭出了自己的WorldCreator.尽管它因此能创造出一个有山有树有房子的世界,但是白 ...

  2. [学习笔记]设计模式之Builder

    写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 作为一个新入职的魔导士呢,哦不,是程序员,我以为并没有太多机会去设计项目的软件架构.但是,工作一段时间之后,自己渐渐意识到,哪怕是自己 ...

  3. [学习笔记]设计模式之Adapter

    写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 Adapter(适配器)模式主要解决接口不匹配的问题.为此,让我们要回到最初Builder模式创建平行世界时,白雪公主和小霍比特人的谜 ...

  4. [学习笔记]设计模式之Bridge

    写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 “魔镜啊魔镜,谁是这个世界上最美丽的人?”月光中,一个低沉的声音回荡在女王的卧室.“是美丽的白雪公主,她正和小霍比特人们幸福快乐地生活 ...

  5. [学习笔记]设计模式之Prototype

    写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 在笔记Builder模式中,我们曾见到了最初用于创建平行世界的函数createWorld,并且它是Mage类的成员函数(毕竟是专属于魔 ...

  6. [学习笔记]设计模式之Command

    为方便读者,本文已添加至索引: 设计模式 学习笔记索引 写在前面 在上篇Chain of Responsibility(职责链)模式笔记中,我们学习了一种行为型设计模式.今天,我们继续这一主题,来学习 ...

  7. [学习笔记]设计模式之Chain of Responsibility

    为方便读者,本文已添加至索引: 设计模式 学习笔记索引 写在前面 最近时间比较紧,所以发文的速度相对较慢了.但是看到园子里有很多朋友对设计模式感兴趣,我感觉很高兴,能够和大家一起学习这些知识. 之前的 ...

  8. [学习笔记]设计模式之Composite

    为方便读者,本文已添加至索引: 设计模式 学习笔记索引 写在前面 在Composite(组合)模式中,用户可以使用多个简单的组件以形成较大的组件,而这些组件还可能进一步组合成更大的.它重要的特性是能够 ...

  9. [学习笔记]设计模式之Flyweight

    为方便读者,本文已添加至索引: 设计模式 学习笔记索引 写在前面 Flyweight(享元)模式运用共享技术,可以有效地支持大量细粒度的对象.今天我们会去参观小霍比特人们的酿酒工坊……等等,不是享元模 ...

随机推荐

  1. 支持Python 2.7的pylot

    想用pylot测试一下板子上面的嵌入式web server.结果报错. E:\pylot_1.26>run.py -a 2 Traceback (most recent call last): ...

  2. JQuery- 动画与效果

    这几天做网站,刚好用到! 1.基本效果 匹配元素从左上角开始变浓变大或缩小到左上角变淡变小 ①隐藏元素 除了可以设置匹配元素的display:none外,可以用以下函数 hide(speed,[cal ...

  3. [置顶] 如何访问web文件夹之外的文件

        在编写项目时,遇到一个如何访问web文件夹之外的文件的问题.因为我要制作一个浏览图片和pdf文件的一个简单网站.但问题是图片的文件夹和pdf文件的文件夹都是其他程序生成的,自然也就是不是网站w ...

  4. 从struts2.1开始Convention零配置

    从struts2.1开始,struts2不再推荐使用Codebehind作为零配置插件,而是改为使用Convention插件来支持零配置,和Codebehind相比,Convention插件更彻底,该 ...

  5. Rsync同步工具安装文档

    (1)下载Rsync源代码进行安装 (2)1'   cd rsync 2'   ./configure   --prefix=/usr/local/rsync 3'   make 4'   make  ...

  6. FastDFS分布文件系统[转]

    FastDFS是为互联网应用量身定做的一套分布式文件存储系统,非常适合用来存储用户图片.视频.文档等文件.对于互联网应用,和其他分布式文件系统相比,优势非常明显.具体情况大家可以看相关的介绍文档,包括 ...

  7. Hadoop-2.4.1学习之Map任务源代码分析(下)

    在Map任务源码分析(上)中,对MAP阶段的代码进行了学习,这篇文章文章将学习Map任务的SORT阶段.假设Reducer的数量不为0.则还须要进行SORT阶段.但从上面的学习中并未发现与MAP阶段运 ...

  8. Makefile详解--隐含规则

    Makefile详解--隐含规则(转) Makefile系列文章,这里有个前辈连续洗了一个系列来介绍,共有26篇博客文章. http://www.cppblog.com/ivenher/archive ...

  9. Linux下git的配置

    需求和环境 硬件:一台装有Ubuntu14.04的PC 软件:git-core.openssh-server.openssh-client Git的安装 sudo apt-get install gi ...

  10. 菱形实现气泡Bubble,菱形画箭头,菱形画三角形

    菱形实现气泡Bubble,菱形画箭头,菱形画三角形 >>>>>>>>>>>>>>>>>>&g ...