在GOF的《设计模式:可复用面向对象软件的基础》一书中对代理模式是这样说的:为其他对象提供一种代理以控制对这个对象的访问。结合上面的游戏代理的例子和下面的图,我们来进行分析一下。以前你是这样玩游戏:

现在有了游戏代理,你是这样玩游戏:

代理服务器干了什么?它代替你去和游戏服务器进行交互。它访问游戏服务器的速度比你使用校园网访问游戏服务器的速度快很多。所以,你的游戏延迟就下来了。

代理模式分为四类:远程代理,虚代理,保护代理和智能引用。在下面使用场合会对这四种进行分别介绍。

UML类图


Proxy

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

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

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

[DP]上的定义:为其他对象提供一种代理以控制对这个对象的访问。有四种常用的情况:(1)远程代理,(2)虚代理,(3)保护代理,(4)智能引用。本文主要介绍虚代理和智能引用两种情况。

考虑一个可以在文档中嵌入图形对象的文档编辑器。有些图形对象的创建开销很大。但是打开文档必须很迅速,因此我们在打开文档时应避免一次性创建所有开销很大的对象。这里就可以运用代理模式,在打开文档时,并不打开图形对象,而是打开图形对象的代理以替代真实的图形。待到真正需要打开图形时,仍由代理负责打开。这是[DP]一书上的给的例子。下面给出代理模式的UML图。

class Image
{
public:
Image(string name): m_imageName(name) {}
virtual ~Image() {}
virtual void Show() {}
protected:
string m_imageName;
};
class BigImage: public Image
{
public:
BigImage(string name):Image(name) {}
~BigImage() {}
void Show() { cout<<"Show big image : "<<m_imageName<<endl; }
};
class BigImageProxy: public Image
{
private:
BigImage *m_bigImage;
public:
BigImageProxy(string name):Image(name),m_bigImage() {}
~BigImageProxy() { delete m_bigImage; }
void Show()
{
if(m_bigImage == NULL)
m_bigImage = new BigImage(m_imageName);
m_bigImage->Show();
}
};
int main()
{
Image *image = new BigImageProxy("proxy.jpg"); //代理
image->Show(); //需要时由代理负责打开
delete image;
return ;
}

转载请标明出处 http://blog.csdn.net/wuzhekai1985

在这个例子属于虚代理的情况,下面给两个智能引用的例子。一个是C++中的auto_ptr,另一个是smart_ptr。自己实现了一下。先给出auto_ptr的代码实现:

template<class T>
class auto_ptr {
public:
explicit auto_ptr(T *p = ): pointee(p) {}
auto_ptr(auto_ptr<T>& rhs): pointee(rhs.release()) {}
~auto_ptr() { delete pointee; }
auto_ptr<T>& operator=(auto_ptr<T>& rhs)
{
if (this != &rhs) reset(rhs.release());
return *this;
}
T& operator*() const { return *pointee; }
T* operator->() const { return pointee; }
T* get() const { return pointee; }
T* release()
{
T *oldPointee = pointee;
pointee = ;
return oldPointee;
}
void reset(T *p = )
{
if (pointee != p) {
delete pointee;
pointee = p;
}
}
private:
T *pointee;
};

阅读上面的代码,我们可以发现 auto_ptr 类就是一个代理,客户只需操作auto_prt的对象,而不需要与被代理的指针pointee打交道。auto_ptr 的好处在于为动态分配的对象提供异常安全。因为它用一个对象存储需要被自动释放的资源,然后依靠对象的析构函数来释放资源。这样客户就不需要关注资源的释放,由auto_ptr 对象自动完成。实现中的一个关键就是重载了解引用操作符和箭头操作符,从而使得auto_ptr的使用与真实指针类似。

我们知道C++中没有垃圾回收机制,可以通过智能指针来弥补,下面给出智能指针的一种实现,采用了引用计数的策略。

template <typename T>
class smart_ptr
{
public:
smart_ptr(T *p = ): pointee(p), count(new size_t()) { } //初始的计数值为1
smart_ptr(const smart_ptr &rhs): pointee(rhs.pointee), count(rhs.count) { ++*count; } //拷贝构造函数,计数加1
~smart_ptr() { decr_count(); } //析构,计数减1,减到0时进行垃圾回收,即释放空间
smart_ptr& operator= (const smart_ptr& rhs) //重载赋值操作符
{
//给自身赋值也对,因为如果自身赋值,计数器先减1,再加1,并未发生改变
++*count;
decr_count();
pointee = rhs.pointee;
count = rhs.count;
return *this;
}
//重载箭头操作符和解引用操作符,未提供指针的检查
T *operator->() { return pointee; }
const T *operator->() const { return pointee; }
T &operator*() { return *pointee; }
const T &operator*() const { return *pointee; }
size_t get_refcount() { return *count; } //获得引用计数器值
private:
T *pointee; //实际指针,被代理
size_t *count; //引用计数器
void decr_count() //计数器减1
{
if(--*count == )
{
delete pointee;
delete count;
}
}
};

[设计模式] 12 代理模式 proxy的更多相关文章

  1. 乐在其中设计模式(C#) - 代理模式(Proxy Pattern)

    原文:乐在其中设计模式(C#) - 代理模式(Proxy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 代理模式(Proxy Pattern) 作者:webabcd 介绍 为 ...

  2. 大熊君说说JS与设计模式之------代理模式Proxy

    一,总体概要 1,笔者浅谈 当我们浏览网页时,网页中的图片有时不会立即展示出来,这就是通过虚拟代理来替代了真实的图片,而代理存储了真实图片的路径和尺寸,这就是代理方式的一种. 代理模式是比较有用途的一 ...

  3. 二十四种设计模式:代理模式(Proxy Pattern)

    代理模式(Proxy Pattern) 介绍为其他对象提供一个代理以控制对这个对象的访问. 示例有一个Message实体类,某对象对它的操作有Insert()和Get()方法,用一个代理来控制对这个对 ...

  4. Java基础-设计模式之-代理模式Proxy

    代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理 ...

  5. c#设计模式之代理模式(Proxy Pattern)

    引言 代理这个词语,大家在现实世界已经频繁的接触过,例如火车站代理售票点,因为这些代理售票点的存在,我们不必要去火车站的售票处就可以查询或者取到火车票.代理点本身是没有能力生产车票的,我们在代理处享受 ...

  6. 设计模式三: 代理模式(Proxy) -- JDK的实现方式

    简介 代理模式属于行为型模式的一种, 控制对其他对象的访问, 起到中介作用. 代理模式核心角色: 真实角色,代理角色; 按实现方式不同分为静态代理和动态代理两种; 意图 控制对其它对象的访问. 类图 ...

  7. 设计模式 笔记 代理模式 Proxy

    //---------------------------15/04/21---------------------------- //Proxy 代理模式-----对象结构型模式 /* 1:意图: ...

  8. 【设计模式】—— 代理模式Proxy

    前言:[模式总览]——————————by xingoo 模式意图 代理模式为其他的对象增加一个代理对象,进行访问控制.从而避免直接访问一个对象,造成效率或者安全性上的降低. 应用场景 1 远程代理, ...

  9. 结构型设计模式之代理模式(Proxy)

    结构 意图 为其他对象提供一种代理以控制对这个对象的访问. 适用性 在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用P r o x y 模式.下面是一 些可以使用P r o x y 模式常见 ...

随机推荐

  1. windows 7 打开控制面板的命令

    在开始菜单中键入contrl,回车就进入了控制面板,比较快

  2. ArcSDE for Microsoft SQL Server Post Installation图解(转)

    ArcSDE for Microsoft SQL Server Post Installation图解 使用ArcSDE作为空间数据引擎时,经常遇到服务无法启动的情况(启动服务时提示:本地计算机上的a ...

  3. C++ Maps 映射

    C++ Maps是一种关联式容器,包含“关键字/值”对 begin() 返回指向map头部的迭代器 clear() 删除所有元素 count() 返回指定元素出现的次数 empty() 如果map为空 ...

  4. HDU 1954 Subway tree systems (树的最小表示法)

    题意:用一个字符串表示树,0代表向下走,1代表往回走,求两棵树是否同构. 分析:同构的树经过最小表示会转化成两个相等的串. 方法:递归寻找每一棵子树,将根节点相同的子树的字符串按字典序排列,递归回去即 ...

  5. 【风马一族_Java】 Java的文件类 java.io

    BufferedReader 从字符输入流中读取文本,缓冲各个字符,从而实现字符.数组和行的高效读取. 可以指定缓冲区的大小,或者可使用默认的大小.大多数情况下,默认值就足够大了. 通常,Reader ...

  6. setuid函数解析

    在讨论这个setuid函数之前,我们首先要了解的一个东西就是内核为每个进程维护的三个UID值.这三个UID分别是实际用户ID(real uid).有效用户ID(effective uid).保存的设置 ...

  7. 单选复选按钮以及Toast学习笔记

    1:单选按钮是以组的形式呈现,xml布局文件中需要定义一个RadioGroup,然后在这个组内再定义RadioButton.在java代码中为该按钮添加监听时,需要用组名来引用对应的方法setOnCh ...

  8. 解决前端浏览器传JSON对像到服务端后全部变成string类型的方法

    这几天公司用nodejs+mongodb来做些东西,UI用的是kendo UI 碰到一个问题: 举个例子var a={"name":"张三","age ...

  9. Python开发【第一篇】Python模块中特殊变量

    模块中特殊变量 生产环境中,常用的就是__name__和__file__ __doc__ __package__ __cached__ __name__ __file__ 一. __doc__  #获 ...

  10. .NET特性-Attribute

    两篇文章有助于学习Attribute特性的概念. http://blog.csdn.net/byondocean/article/details/6802111 http://www.cnblogs. ...