代理模式
代理模式的定义:为目标对象提供一种代理以控制对这个对象的访问。
我们先来看一下代理模式的结构图:
我们先来看看Proxy的request()方法里的代码:
public void request() { //在转调具体的目标对象前,可以执行一些处理功能 //转调具体的目标对象的方法 realSubject.request(); //在转调具体的目标对象后,可以执行一些处理功能 }
客户端代码:
static void Main(string[] args) { Subject proxy = new Proxy(new RealSubject()); proxy.request(); }
由上面的结构图及代码可以看出,代理模式是通过创建一个代理对象,用这个代理对象去代表真实的对象,客户端得到这个代理对象后,对客户端没有什么影响,就跟得到了真实对象一样来使用。当客户端操作这个代理对象的时候,实际上功能最终还是会由真实的对象来完成,只不过是通过代理操作的,也就是客户端操作代理,代理操作真正的对象,这样就不会破坏原有对象的封装性。正是因为有代理对象夹在客户端和被代理真实对象中间,相当于一个中转,那么在中转的时候就可以玩很多花样,比如判断一下权限,等。
根据不同的花样,代理被分成了很多种:
虚代理:虚代理可实现延迟加载,即当创建一个很大的对象时,该对象只有在需要的时候才会被真正创建。这里举一个简单的例子,要从数据库里读取人员信息People(ID,Name,Sex,Work),假设Sex跟Work的信息量很大,所以我们可以延迟加载它们,这里只写“Proxy”,“Subject”跟“RealSubject”就不写了
class PeopleProxy:Subject { public string getId() { return realSubject.getId(); } public void setId(string id) { realSubject.setId(id); } public string getName() { return realSubject.getName(); } public void setName(string name) { realSubject.setName(name); } private bool isLoad=false; public string getSex() { //调用目标对象方法前作一些处理 if(!isLoad) { //延迟加载(对于大信息量的字段,用到的时候才去数据库读取) load(); isLoad=true; } //调用目标对象的方法 return realSubject.getSex(); } public string getWork() { //调用目标对象方法前作一些处理 if(!isLoad) { //延迟加载(对于大信息量的字段,用到的时候才去数据库读取) load(); isLoad=true; } //调用目标对象的方法 return realSubject.getWork(); } private void load() { string id = getId(); //只去数据库读取sex跟work这俩字段 realSubject.setSex(sex); realSubject.setWork(work); } }
远程代理:用来在不同的地址空间上代表同一个对象,这个不同的地址空间可以在本机,也可以在其它机器上。
.NET中webservice技术就是用远程代理来实现的,通常代理类的生成是由vs帮我们创建的(其中MyWeather.WeatherWebService就是一个代理类),这篇文章讲述了怎么自己来实现一个webservice代理类。
copy-on-write(写时复制)代理:在客户端操作的时候,只有对象确实改变了,才会真的拷贝一个目标对象,算是虚代理的一个分支。
保护代理:控制对原始对象的访问,如果有需要,可以给不同的用户提供不同的访问权限,以控制他们对原始对象的访问。
Cache代理:为那些昂贵操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
防火墙代理:保护对象不被恶意用户访问和操作。
同步代理:使多个用户能够同时访问目标对象而没有冲突。
智能指引:在访问对象时执行一些附加操作,比如,对指向实际对象的引用计数、第一次引用一个持久对象时,将它载入内存等。
代理模式本质:控制对象访问。