代理模式(Proxy)

一、   什么是代理模式

先来看看官方的说法,代理模式就是为其它对象提供一种代理,以控制对这个对象的訪问。

看来这个官方的说法的确有点官方,看了还是让人感觉不点不知所措,还是不明确代理模式是什么,到底是用来做什么的。

事实上代理这个名词,对于我们来说事实上并不陌生,生活中有非常多关于代理的样例。比如校园代理等,就以校园代理来讲,这个校园代理就是为他相应的上司的作代理,而这个校园代理的工作就是訪问校园中的学生,比如对学生进行问卷之类的事。在这个样例中,学生就是官方说法中的其它对象,校园代理的上司就通过控制这个校园代理来控制对学生的訪问。这下应该明确一点了吧。

二、   代理模式的类图

三、   代理模式的实现代码(C++实现)

以上面说的校园代理为样例,我们来一睹代理模式的风採,为了更好地理解这个模式,还是要作一点的解释的。在以下的代码中,将出现三个类,Worker、Boss和SchoolProxy,他们分别相应上图的Subject、RealSubject和Proxy这三个类,而这些类中的doSurvey方法,就是相当于上图中的Request方法。

注:事实上上图仅仅是一个代理模式的UML模型图,Request事实上是代表着全部Proxy和RealSubject的共用接口,而不仅仅是这里所写的一个。

事实上现代码例如以下(proxy.cpp):

1、Worker类的定义例如以下,它有一个doSurvey的接口

class Worker
{
public:
virtual void doSurvey() = 0;
virtual ~Worker(){}
};

2、Boss类定义例如以下,它继承Worker类,并实现doSurvey接口

class Boss : public Worker
{
public:
virtual void doSurvey()
{
cout << "The ABCDE company do sruvey!" << endl;
}
};

3、SchoolProxy类定义例如以下,它相同继承Worker类,并实现doSurvey接口,该类维护一个Boss类的对象的引用,并在它的中doSurvey方法中调用Boss的doSurvey方法。

class SchoolProxy : public Worker
{
public:
SchoolProxy():
_boss(NULL)
{
}
virtual ~SchoolProxy()
{
if(_boss != NULL)
{
delete _boss;
}
}
SchoolProxy(const SchoolProxy&proxy)
{
_boss = newBoss(*proxy._boss);
}
SchoolProxy& operator=(const SchoolProxy &rhs)
{
if(this != &rhs)
{
SchoolProxytmp_proxy(rhs);
Boss *tmp_boss =tmp_proxy._boss;
tmp_proxy._boss = _boss;
_boss = tmp_boss;
}
return *this;
}
virtual void doSurvey()
{
if(_boss == NULL)
{
_boss = new Boss();
}
_boss->doSurvey();
}
private:
Boss *_boss;
};

注:此类中的Boss也可不使用指针,而直接使用对象。可是由于java或C#这类的语言并不支持栈上对象,全部的对象都是new出来的,所以这种写法与java和C#更类似。

4、调用方法例如以下:

int main()
{
SchoolProxy *proxy = new SchoolProxy();
proxy->doSurvey();
delete proxy;
return 0;
}

从上面的代码,我们能够清晰地看到,校园代理SchoolProxy是怎样帮助它的Boss来完毕做调查的工作的。

四、   代理模式的应用

看了上面的代码,我想代理模式的操作和原理,大家都差点儿相同能够理解了,可是事实上代理还是有不仅仅一种的,依据通常的使用,能够分为四类。

1)            远程代理

它为一个对象在不同的地址空间提供局部代表。这样就能够隐藏一个对象存在于不同地址空间的事实,它的样例就是WebServer。

2)            虚拟代理

它依据需求创建开销比較大的对象,通过它来存放实例化须要非常长时间的真实对象。比如,当我们浏览网页时,网页中可能有一些比較大的图片,尽管图片比較大,可是你还是能够非常快地打开网页,然而图片却不能在第一时间显示,可能要在几秒后才干正常显示,在这里就是通过虚拟代理来替换真实的图片。

3)            保护代理

它用于控制对原对象的訪问,保护代理用于对象应该有不同的訪问权限的时候。

4)            智能引用

它用于指当调用真实对象时,代理运行额外的一些操作,处理另外一些事情。比如C++中的智能指针,它代替了简单的指针,它会对它所指向的对象运行一些额外的操作。

五、   代理模式的真实应用之share_ptr

看了上面的代码,看了上面的讲解,你可能认为代理模式没什么作用,那么你就错了,以下来看看,上面四种代理模式当中一种智能引用的强大用处。

有使用过C++的程序猿,肯定知道智能指针这个好东西,它能够让大大降低我们对内存的管理难度,由于它通过以对象管理资源的方法,使指针指向向的堆内存像栈内存一样,能够自己主动释放。

以下就以本人实现的share_ptr来说明智能引用的代理模式的应用,首先来看看类的定义:

template <typename T>
class SharePtr
{
public:
SharePtr(T *tptr = NULL);
SharePtr(const SharePtr &sptr);
SharePtr& operator=(const SharePtr &sptr);
SharePtr& operator=(T *tptr);
~SharePtr();
T&operator*()const;
T*operator->()const;
bool operator==(const SharePtr &sptr)const;
bool operator!=(const SharePtr &sptr)const;
bool operator==(const T *tptr)const;
bool operator!=(const T *tptr)const;
const T* getPtr()const;
private://function
void _decUsed();
inline void _nullTest()const;
inline bool _isSame(const SharePtr &sptr)const;
inline bool _isSame(const T *tptr)const;
private://data
T *_ptr;
size_t *_used;//引用计数,为0时释放ptr指向的对象
};

它的定义就仅仅有这么多了,看了上面的定义,你能够会产生疑问,这个真的应用了上面所说的代理模式吗?上面的代理模式不是要有一个Subject类、一个RealSubject类和一个Proxy类的吗?而RealSubject类和Proxy是Subject的子类,须要定义Subject的接口的吗?为什么这里仅仅有一个类呢?

如今你看不出来,我并不怪你。看下去自然会明确。

智能指针,这里以share_ptr为例,它的目的就是通过一个类来模仿一个指针的行为,并提供指针没有的功能,就是当指针变量出了作用域后,自己主动处理指针指向的内存的功能。所以上面你看到的SharePtr模板类,就相当于Proxy类。

那RealSubject类呢?由于智能指针是指针的代理,那么RealSubject类当然就是SharePtr<T>中的成员变量T,我认为说是T类型的指针T*更加恰当。哈哈,奇异吧!

那么Subject类呢?这里是什么充当这个类呢?从代理模式的类图能够看到Subject类定义的是RealSubject和Proxy的共同拥有接口,你想想看,既然RealSubject是一个指针,那么它的操作就是*、->、==、!=和 =这五种了,由于这些操作本来就是原生的操作,并非什么特别的规定,所以在这里并没有这个Subject,可是能够看到,这些共同拥有的接口或者说是操作,上面的SharePtr类中,还是有实现的。

换一个角度来说,*、->、==、!=和 =这五类操作就是Subject类中的接口,可是在这里并没有必要实现一个Subject的基类,然后让SharePtr来继承它。由于指针并不须要继承Subject就已经具有这五类操作了。所以这里把这个类省去了。

这下你应该明确,为什么这里的一个类就是一个代理模式了吧。事实上我认为学习设计模式最重要的还是学习它的思想,学习的解决这个问题的方法以及怎样用它架构我们的程序,而不是对比着类图或者它的定义来生搬硬套。上面的智能指针就是一个样例。

事实上智能指针并非一个指针变量,它仅仅是一个定义在栈上的对象,通过运算符重载使其行为像一个指针变量。当程序运行出了其作用域后,就会析构销毁,运行相应的操作。以下再来简单看看,这个代理为我们做了一些什么额外的事情。

比如,当对象释放时,会进行例如以下操作:

template <typename T>
SharePtr<T>::~SharePtr()
{
_decUsed();
}
template <typename T>
void SharePtr<T>::_decUsed()
{
--*_used;
if(*_used ==0)
{
if(_ptr!= NULL)
{
delete _ptr;
_ptr= NULL;
}
delete _used;
_used = NULL;
}
}

很多其它的实现和额外操作,可查看源码。

六、   Android中的代理模式

在Android中代理模式也是使用广泛的,比如ActivityManagerProxy类就是一个代理,它是ActivityManagerNative的代理,也就是说ActivityManagerProxy是上面所说的Proxy类,而ActivityManagerNative就相当于RealSubject类,它们都有一个共同拥有的接口IActivityManager。

在这里另一个重要的类:ActivityManager,它相当于代理模式的类图中的client。在这个类中,能够看到大量的getxxx函数,这些函数,都会调用到ActivityManagerNative类的getDefault()方法,而该方法会获得一个共用的单例的IActivityManager引用,然后通过多态来调用代理中的实现。

注:由于时间的关系,没有深入去研究。

七、   代码地址

http://download.csdn.net/detail/ljianhui/7468509

代理模式与Android的更多相关文章

  1. Android中的代理模式

    代理的概念:为某个对象提供一个代理,以控制对这个对象的访问. 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代.代理类负责请求的预处理.过滤.将请求分派给委托类处 ...

  2. [旧][Android] 代理模式

    备注 原发表于2016.05.21,资料已过时,仅作备份,谨慎参考 代理模式是什么 如上图所示,代理代表着另一终端中的某个真实服务对象,Client 调用代理(Client helper)的方法,然后 ...

  3. 理解Android系统的进程间通信原理(一)----RPC中的代理模式

    Android系统中的进程间通信是通过一个轻量级的RPC(Remote Procedure Call远程进程调用)和AIDL(Android Interface Definination Langua ...

  4. Android开发中无处不在的设计模式——动态代理模式

    继续更新设计模式系列.写这个模式的主要原因是近期看到了动态代理的代码. 先来回想一下前5个模式: - Android开发中无处不在的设计模式--单例模式 - Android开发中无处不在的设计模式-- ...

  5. Android设计模式之代理模式

    代理模式: 为其他对象提供一种代理以控制对这个对象的访问 Subject类定义了RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy inte ...

  6. (转 )【Android那些高逼格的写法】InvocationHandler与代理模式

    转自这个公众号: 今天会聊一下InvocationHandler.说到InvocationHandler不得不提到的就是代理模式,什么是代理模式,举个例子,你玩游戏,花钱请个代练,代练其实是登录你的账 ...

  7. Proxy 代理模式

    简介 代理模式是用一个简单的对象来代替一个复杂的或者创建耗时的对象. java.lang.reflect.Proxy RMI 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对 ...

  8. 黑马程序员:Java基础总结----静态代理模式&动态代理

    黑马程序员:Java基础总结 静态代理模式&动态代理   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public  class  Ts {   ...

  9. Proxy 代理模式 动态代理 cglib MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

随机推荐

  1. 追索权 Eclipse + NDK error: stray &#39;\24&#39; in program

    [size=16px][b][color=#FF0000]追索权 Eclipse + NDK  error: stray '\24' in program[/color][b][/b][/b][/si ...

  2. FreeMarker整合Spring 3(转)

    开发环境: System:Windows WebBrowser:IE6+.Firefox3+ JavaEE Server:tomcat5.0.2.8.tomcat6 IDE:eclipse.MyEcl ...

  3. Action、Category、Data、Extras知识具体解释

    开头 Intent作为联系各Activity之间的纽带,其作用并不仅仅仅仅限于简单的数据传递.通过其自带的属性,事实上能够方便的完毕非常多较为复杂的操作.比如直接调用拨号功能.直接自己主动调用合适的程 ...

  4. Java 内部类分析

    一.简介 因为现在是Android开发实习生.发现在发展过程中越来越多,但他们知道什么时候该使用真实的情况,但没有获得,例如,使用内部类,因此,学习和自己的总结后发现,通过互联网的信息,家分享,如有不 ...

  5. 如何使用 iOS 7 的 AVSpeechSynthesizer 国家有声读物(4)

    控制:我们一定要学会控制 尤达大师(电影<星球大战>)有话:的关键在于控制.这本故事书是一个字一个字读出来,我愿意为它添加两个button,音调和语速,以便我们能够调整语音合成实时的时候. ...

  6. hdu1381 Crazy Search(hash map)

    题目意思: 给出一个字符串和字串的长度,求出该字符串的全部给定长度的字串的个数(不同样). 题目分析: 此题为简单的字符串哈hash map问题,能够直接调用STL里的map类. map<str ...

  7. SVG图像技术摘要

    该公司今天没有,研究了最近流行SVG技术,发现,随着css3不断流行,和浏览器技术的发展,SVG网站将取代大量的图片,成为主流站点图片展示. AI是我们经常使用的矢量图编辑器,如今AI能够直接另存SV ...

  8. spring中间scope详细解释

    0.思维导图 1. scope概论 spring中scope是一个很关键的概念.简单说就是对象在spring容器(IOC容器)中的生命周期,也能够理解为对象在spring容器中的创建方式. 2. sc ...

  9. php 简单的存在 (方法之间的神奇作用:容错)

    <span style="font-family:KaiTi_GB2312;font-size:18px;"><?php // 重载 class Person{ ...

  10. ftp的port和pasv型号比较

    一个.ftp的port和pasv工作方式        FTP使用2个TCPport,首先是建立一个命令port(控制port),然后再产生一个数据port. 国内非常多教科书都讲ftp使用21命令p ...