一、引出模式
代理,在生活我我们非常常见。比如在中学时期,总追过女孩子吧!身为码农的我们,没追过也没关系,总看过别人追过女孩子吧!这里出现了3个重要人物,甲想追求乙,但甲又不认识乙,幸好乙的闺蜜丙是甲的小学同学,于是呢,甲就通过丙给乙传递一些纸条,情书之类的。在这里面同学丙就充当着一个代理的角色,甲无法直接找到乙说话,只能通过丙给乙传递消息。
二、认识模式
1.定义:
代理模式为目标对象提供一种代理,并由该代理对象控制对这个目标对象的访问。
2.模式结构和说明
Subject:目标接口,定义代理和具体目标对象的接口,这样就可以在任何地方使用具体目标对象的地方使用代理对象。
RealSubject:具体的目标对象,真正实现目标接口的功能。
Proxy:代理对象,主要有如下功能:
* 实现和具体的目标对象一样的接口,这样可以使用代理来代替具体的目标对象
* 保存一个指向具体目标对象的引用,可以在需要时调用具体的目标对象。
* 可以控制对具体目标对象的访问,并可以负责创建和删除它。
3.示例代码
class Program { static void Main(string[] args) { Subject subject = new Proxy(new RealSubject()); subject.Request(); Console.ReadKey(); } } /// <summary> /// 定义具体的目标对象和代理公有接口 /// </summary> public abstract class Subject { public abstract void Request(); } /// <summary> /// 具体的目标对象,是真正被代理的对象 /// </summary> public class RealSubject : Subject { public override void Request() { //执行真正要实现的功能 Console.WriteLine("调用真实对象"); } } /// <summary> /// 代理对象 /// </summary> public class Proxy : Subject { //持有被代理的具体目标对象 private RealSubject subject = null; //注入具体被代理的目标对象 public Proxy(Subject subject) { this.subject = (RealSubject) subject; } public override void Request() { //转调之前可以做一些事情,比如权限判断等 //转调具体目标对象的方法 subject.Request(); //转调之后也可以做一些事情 } }
三、理解模式
1.模式功能:
代理模式通过创建一个代理对象,用这个对象去代表真实对象,当客户端操作这个给代理对象时,实际上功能最终还是会有真实对象来实现,只不过是通过代理操作的。
正是因为代理对象夹在客户端与真实对象之间,相当于中转站,所以在中转前后可以做很多事情,比如权限判断。
2.代理分类:
* 远程代理:为一个位于不同的地址空间的对象提供一个局域代表对象。这个不同的地址空间可以是在本机器中,也可是在另一台机器中。远程代理又叫做大使(Ambassador)。
* 虚拟代理:根据需要创建一个资源消耗较大的对象,使得此对象只在需要时才会被真正创建。
* Copy-on-Write代理:虚拟代理的一种。把复制(克隆)拖延到只有在客户端需要时,才真正采取行动。
* 保护代理:控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。
* Cache代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
* 防火墙代理:保护目标,不让恶意用户接近。
* 同步化代理:使几个用户能够同时使用一个对象而没有冲突。
* 智能指引:当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来等。
在所有种类的代理模式中,虚拟(Virtual)代理、远程(Remote)代理、智能引用代理(Smart Reference Proxy)和保护(Protect or Access)代理是最为常见的代理模式。
3.具体目标对象和代理对象的关系
从模式图来看,好像一个具体目标类就有一个代理类,其实不是这样的。如果代理类能完全通过接口来操作它所代理的目标对象,那么代理对象就不需要知道具体的目标对象,这样就无需为每一个具体目标对象都创建一个代理类。
4.保护代理细说
保护代理是一种控制对原始对象访问的代理,多用于对象应该有不同的访问权限的时候。保护代理会检查调用者是否具有请求所必需的访问权限,如果没有,就不会调用目标对象,从而实现对目标对象的保护。
示例:现在有个订单系统,一旦订单被创建,那么只有创建人才能需改和删除订单。
class Program { static void Main(string[] args) { #region 保护代理 #endregion OrderApi orderApi = new ProxyOrder(new Order("设计模式", 100, "zxj")); orderApi.SetProductName("哈哈哈", "zxj"); Console.ReadKey(); } } #region 保护代理 /// <summary> /// 订单接口 /// </summary> public abstract class OrderApi { public abstract void SetProductName(string ProductName, string ProductUser); } /// <summary> /// 订单 /// </summary> public class Order : OrderApi { /// <summary> /// 产品名称 /// </summary> public string ProductName { get; set; } /// <summary> /// 产品数量 /// </summary> public int ProductNum { get; set; } /// <summary> /// 操作员 /// </summary> public string ProductUser { get; set; } public Order(string PeoductName, int ProductNum, string ProductUser) { this.ProductName = PeoductName; this.ProductNum = ProductNum; this.ProductUser = ProductUser; } public override void SetProductName(string ProductName, string ProductUser) { throw new NotImplementedException(); } } public class ProxyOrder : OrderApi { private Order order; public ProxyOrder(Order order) { this.order = order; } public override void SetProductName(string ProductName, string ProductUser) { if (order.ProductName != null && order.ProductUser.Equals(ProductUser)) { Console.WriteLine("{0}可以修改", ProductUser); } else { Console.WriteLine("{0}无权修改", ProductUser); } } } #endregion
5.模式特点
* 远程代理:隐藏了一个对象存在不同的地址空间的事实。
* 虚代理:可以根据需要创建“大”对象,只要到必须创建对象的时候,虚代理才会创建对象。
* 保护代理:可以在访问一个对象的前后,附加执行很多操作,除了权限控制之外,还可以进行很多业务,也就是说,可以通过代理来给目标对象增加功能。
* 智能指引:和保护代理类似,可以在访问一个对象前后附加其他操作,如果存有保护性质的,就算保护代理,其他就算是智能指引。
6.代理模式的选用
* 需要为一个对象在不同的地址空间提供局部代表的时候,可以使用远程代理。
* 需要按照需要创建开销很大的时候,可以使用虚代理。
* 需要控制原始对象的访问的时候,可以使用保护代理。
* 需要在访问对象执行一些附加操作的时候,可以使用智能代理。
7.模式本质
控制对象访问
代理模式通过代理目标对象,把代理对象插入到客户和目标对象之间,从而为客户和目标引入一定的间接性。正是这个间接性,给力代理对象很大的活动空间,可以在目标对象前后,附加很多操作,从而实现新的功能或是扩展。
从实现哈桑看,代理模式主要使用对象的组合和委托,尤其是在静态代理的实现里面。也可以采用对象继承的方式来实现代理,比如上面的保护代理示例
8.相关模式
* 代理模式与适配器模式
这两个模式有一定的相似性,它们都为另一个对象提供间接性访问,而且都是从自身以外的一个借口想这个对象转发请求。
但是在功能上,适配器模式主要用来解决接口之间不匹配的问题。它通常是为所适配的对象提供一个不同的接口;而代理模式会实现和目标对象相同的接口。
* 代理模式和装饰模式
这两个模式从实现上相似,都是在转掉调其他对象的前后执行一定的功能。
但是它们的功能和目的是不同的,装饰模式目的是为了让你不生成子类就可以给对象添加指着,也就是为了动态的添加功能;而代理模式的主要目的是控制对对象的访问。