代理模式基本概念及分类*

    代理模式——为其他对象提供一种代理,以控制对这个对象的访问。例如电脑桌面的快捷方式就是一个代理对象,快捷方式是它所引用的程序的一个代理。

    虚拟(Virtual)代理:根据需要创建一个资源消耗较大的对象,使得对象只在需要时才会被真正创建。
    Copy-on-Write代理:虚拟代理的一种,把复制(或者叫克隆)拖延到只有在客户端需要时,才真正采取行动。
    保护(Protect or Access)代理:控制一个对象的访问,可以给不同的用户提供不同级别的使用权限。
    智能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来等。
    防火墙(Firewall)代理:保护目标不让恶意用户接近。
    Cache代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以这些结果。

    为什么要用代理模式*

    中介隔离:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。

    开闭原则,增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。

    代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。

    开发应用场景*

    在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。

    举个栗子*

    UML图
    代理模式—设计模式(C#) - 图1
    代理模式—设计模式(C#) - 图2

    代码

    1. class Program
    2. {
    3. //客户端代码
    4. static void Main(string[] args)
    5. {
    6. Proxy proxy = new Proxy();
    7. proxy.Request();
    8. Console.Read();
    9. }
    10. }
    11. //Subject类,定义了RealSubject和Proxy的公用接口,这样就在任何使用RealSubject的地方都可以用Proxy
    12. abstract class Subject
    13. {
    14. public abstract void Request();
    15. }
    16. //RealSubject类,定义Proxy所代表的真实实体
    17. class RealSubject : Subject
    18. {
    19. public override void Request()
    20. {
    21. Console.WriteLine("真实的请求");
    22. }
    23. }
    24. //Proxy类,保存一个引用使得代理可以访问实体,并提供一个与Subject的接口相同的接口,这样代理可以用来替代实体了
    25. class Proxy:Subject
    26. {
    27. RealSubject realSubject;
    28. public override void Request()
    29. {
    30. if(realSubject==null)
    31. {
    32. realSubject = new RealSubject();
    33. }
    34. realSubject.Request();
    35. }
    36. }

    两种实现方式*

    静态代理
    若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在代码中定义的。 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类。上面的“栗子”就是静态代理。
    动态代理
    代理类在程序运行时创建的代理方式被成为 动态代理。 也就是说,这种情况下,代理类并不是在代码中定义的,而是在运行时根据我们在代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。