zoukankan      html  css  js  c++  java
  • C# Design Patterns (4) Proxy

    本帖介绍 Proxy Pattern (代理模式)。

    --------------------------------------------------------
    本帖的示例下载点:
    https://files.cnblogs.com/WizardWu/090706.zip
    第一、第二个示例为 Console Mode 控制台应用程序,第三个示例为 ASP.NET 网站。
    执行第三个示例需要 Visual Studio 或 IIS,以及 SQL Server 的 Northwind 数据库。
    --------------------------------------------------------

    Proxy Pattern (代理模式)

    The Proxy Pattern provides a surrogate or placeholder for another object to control access to it...
                                     - Design Patterns: Elements of Reusable Object-Oriented Software


    在 GoF 的书中,对 Proxy 模式的定义为:替某个对象,提供一个替身,以控制外界对这个对象的访问。而这个被替身代理的对象 (被代理者),可能是远端的对象、创建时需要高成本或大计算量的对象,或需要安全控制的对象。


    图 1 此图为 Proxy 模式的经典类图

    01_Shell / Program.cs

    上方图 1 的 Class Diagram,以及「Shell (壳)」示例中,我们有一个 Subject 抽像类,这是 RealSubject 和 Proxy 共同的接口,好让任何用户都可将 Proxy 对象 (代理者) 视为 RealSubject 对象 (被代理者,亦即真实的对象) 来处理。

    其中 RealSubject 是真正做事的对象,它是被 Proxy 代理的对象,它的方法是真正做事的函数,并会将一些复杂的工作封装在其方法里,而无须让客户端程序知道实现细节为何;而 Proxy 中的同名称方法 (Request 方法),则可做一些逻辑判断,比如上例中,我们做了 realSubject 是否为 null 的 if 判断,亦即只有客户程序第一次调用此函数时,才去创建 RealSubject 对象。

    客户端和 RealSubject 的互动,都必须透过 Proxy。也由于 Proxy 和 RealSubject 实现了相同的接口,所以客户在任何需要 RealSubject 的地方,都可以用 Proxy 取而代之。此外,Proxy 也控制了客户端对 RealSubject 的访问,其目的如同本帖一开始所说的,因为 RealSubject 可能是网络上远端机器上的对象、创建时需要高成本、或需要安全控管及经过认证才能访问的对象。其原理类似于下图 2 的 HTTP Proxy Server 情景,Client-side 想要前往 Internet 取得 Web Server 上的信息时,可透过 Proxy Server 帮忙处理;其中 Web Server 就如同 RealSubject (被代理者),而 Proxy Server 就如同 Proxy (代理者)。


    图 2 基于代理的远程访问示意图


    Proxy Pattern 依照功能和目的、运行环境的不同,可概略分成以下几种:

    • 远程代理 (Remote Proxy):替网络上机器与机器之间的请求 (request),做「发送 / 接收」和编码、加密…等工作,让用户端程序,只要调用这个代理就能做远端调用,如:Java RMI、Web Service、.NET Remoting、.NET WCF。其中 Web Service 和 WCF,会在引用的客户端程序中,产生 App_WebReferences 文件夹、一些档案和代理类,这些档案即为此种远程代理。
    • 保护代理 (Protection Proxy; Access Proxy):检查调用者是否有权限,去访问真实的对象,例如用户是否有输入正确的密码以通过认证。
    • 智能引用代理 (Smart Reference Proxy):当对象被调用时,提供一些额外的操作,例如:记录对象被调用的次数。
    • 虚拟代理 (Virtual Proxy):让一个资源消耗较大的对象,只有在需要时才会真正被创建,或让真实对象只有在第一次被调用时才创建。
    • 其他,例如:Copy-On-Write Proxy、Cache Proxy、Firewall Proxy、Synchronization Proxy...等 [2], [3], [5]。


    在 GoF 中所举的例子是 Virtual Proxy,举了一个文档中内嵌图片的范例 [4], [11]。若图片是在文档 (如:PDF、PowerPoint) 的其中某一页,用户刚打开文档时,并不需要载入图片,可先用一个 ImageProxy,代替真实的图片被载入;当用户滚动滚动条、转到文档特定的页数时,才真正从硬盘载入图片,以求开启此文档时能加快速度,让用户对此软件有较好的体验。


    图 3 虚拟代理 (Virtual Proxy) 在 GoF 示例的类图,与本帖图 1 的原理相同

    如上图 3 及下方代码所示,当文档被开启时,ImageProxy 对象会代替 (代理) Image 对象被载入,在用户还没转到图片所在的页数时,也就是还没调用 ImageProxy 的 draw 方法时,图片并不会被载入,因此可加速文档的开启、节省内存的使用;当用户转到图片所在页数时,ImageProxy 的 draw 方法才会被调用,此时才真正去创建 Image 对象、从硬盘中载入图片。在此例的 draw 方法里,我们实现了「虚拟代理」,只有在方法「第一次」被调用时,才创建资源消耗大的 Image 对象,以节省内存、控制创建成本昂贵的资源。  

    02_VirtualProxy_Image / Program.cs

    代理的主要目的之一,是把复杂性封装起来,让客户端程序在引用上更容易,而不需要顾虑藏在身后这些复杂的逻辑。如上方这个示例,我们可以把「载入图片、绘制图片在屏幕上」这些较复杂的 .NET API 引用代码,都封装在「被代理者」这个真实 Image 对象的几个自定义方法里。

    此外,我们也可用相同于本示例的逻辑,去实现「保护代理 (Protection Proxy)」的观念,例如要求用户必须输入正确的密码、先通过认证 (Authentication) 后,才能访问 RealSubject 对象、调用其方法。相关的范例,有兴趣的读者可自行去「C# 3.0 Design Patterns」这本书籍的 O'Reilly 英文官方网站上 [9],下载第二章的源代码。


    接下来的第三个示例,为「数据访问代理」的 ASP.NET 例子 [10], [12],用来取得 Northwind 数据库中 Employees 表的记录总数。其类图如下图 4,和本帖第一、第二个示例的类图略有不同,它是将 RealSubject、Proxy 合而为一,变成单一个 DbCommandProxy 类;其左侧的 DbContext 类只是用来协助解决复杂性的问题,包括取得 Web.config 的数据库连接字符串、建立数据库的连接。

    这个 DbCommandProxy 类,实现了 .NET 用来执行 SQL 语句的原生 IDbCommand 接口 [6]。我们为了将复杂性问题、具体的数据库连接方式隔离出来,因此另外提供了一个 DbContext 类,并将这些动作都搬移至 DbContext 类去处理,以另一种设计理念实现了 Proxy Pattern。


    图 4 示例 03_DbProxy / Default.aspx.cs 的类图 

    03_DbProxy / Default.aspx.cs

     
    --------------------------------------------------------

    Proxy Pattern 适用的情景:

    • 对象创建的代价比较高。
    • 仅在操作被请求时创建对象。
    • 对象需要访问控制,如: 权限验证,或访问的同时去执行检查或簿记工作。
    • 需要访问远程站点。
    • 被访问时,需要执行一些逻辑判断的动作。

    Proxy Pattern 的优点:

    • 降低对象使用的复杂度。
    • 增加对象使用的友好度。
    • 提高程序的效率和性能 (如同 HTTP 的 Proxy Server)。

    Proxy Pattern 的缺点:

    • 和一些 Pattern 一样,Proxy Pattern 会造成系统设计中,类的数量增加。

    Proxy Pattern 的其他特性:

    • Proxy Pattern 的结构,类似上一篇帖子的 Decorator Pattern (装饰模式),但是目的不同。
    • Decorator Pattern 替对象加上行为,而 Proxy Pattern 则是控制对象的访问。
    • Proxy Pattern 的关系是在设计阶段就确定好了的,是事先知道的;而 Decorator Pattern 却可以动态地添加。

    --------------------------------------------------------

    本帖的最后,如前三篇帖子一样,照例提供一位 Java 大师 - 结城浩,所绘制的 Proxy Pattern 趣味四格漫画,原地址如下:

    Giko 猫谈 DP 四格漫画:
    http://www.javaworld.com.tw/jute/post/view?bid=44&id=7749&sty=3&age=0&tpg=1&ppg=1#7749
    http://www.hyuki.com/dp/cat_Proxy.html

    ∧_∧  敲敲敲  ╱
    (    )  ∧ ∧ < WCF 算是 Remote Proxy 的一个例子....。
    (    )  (,,゚Д゚)  ╲____________
    ______ (つ_つ____
    |   日∇ ╲|ThinkPad|╲
    |      =========  ╲

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    ____________

    | 喔~、是 Proxy Pattern 吗?
    ╲ __ __________
      |╱
      ∧_∧       ╱
      ( ・∀・)  ∧ ∧ < 你你是谁? ...有..有什么事嬷你?・・・
      (  ⊃ )  (゚Д゚;)  ╲____________
    ________(つ_つ____
    |    日∇ ╲|ThinkPad|╲
    |       =========  ╲

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    __________

    | 被情势所逼,才创建对象的一种 Pattern..恩
    ╲ __ ________
      |╱
      ∧_∧       ╱
      ( ・∀・)  ∧ ∧ < 恩..那算是 Virtual Proxy 的一种....
     (     )  (;゚Д゚)  ╲____________
    _____ (つ_つ____
    |     日∇╲|ThinkPad|╲
    |       =========  ╲

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    __________

    | 项目截止日快到了才开始 coding...恩
    ╲ __ ________
      |╱
     ∧_∧       ╱
     ( ・∀・)  ∧ ∧ < 我又没说!!
     (  ⊃ )  (゚Д゚;) ╲____________
    _____(つ_つ____
    |   日∇ ╲|ThinkPad|╲
    |      =========  ╲
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

             /
      ∧ ∧ < 这可笑不出来
      (    ) ╲_____________
    ∼(___ノ 

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    --------------------------------------------------------

    相关文章:

    [1] Best Practice Software Engineering - Proxy Pattern
    http://best-practice-software-engineering.ifs.tuwien.ac.at/patterns/proxy.html

    [2] .NET设计模式(14):代理模式(Proxy Pattern), 作者: TerryLee
    http://terrylee.cnblogs.com/archive/2006/05/18/403382.html

    [3] C#设计模式(13)-Proxy Pattern
    http://www.cnblogs.com/zhenyulu/articles/48128.html

    [4] Proxy 模式,作者: caterpillar (繁体中文)
    http://caterpillar.onlyfun.net/Gossip/DesignPattern/ProxyPattern.htm
    http://caterpillar.onlyfun.net/Gossip/DesignPattern/ProxyPattern2.htm

    [5] Proxy pattern
    http://blog.csdn.net/rya/archive/2007/12/02/1912130.aspx
    http://www.diybl.com/course/3_program/java/javashl/2007123/89591.html
    http://blog.sina.com.cn/s/blog_5632ed9f0100abms.html
    http://hi.baidu.com/quxiling/blog/item/434d54f429baf9daf2d385d0.html

    [6] IDbCommand 接口 (msdn)
    http://msdn.microsoft.com/zh-cn/library/system.data.idbcommand.aspx
    http://msdn.microsoft.com/zh-cn/library/system.data.idbcommand.executescalar.aspx

    --------------------------------------------------------

    相关书籍:

    [7] Head First 设计模式, Freeman, O'Reilly 出版社, 第十一章
    http://oreilly.com.cn/book.php?bn=978-7-5083-5393-7

    [8] 大话设计模式 (繁体中文翻译本), 程杰 着, 清华大学出版社, 第七章
    http://www.cnblogs.com/cj723/archive/2009/03/12/1409359.html

    [9] C# 3.0 Design Patterns, Judith Bishop, O'Reilly 出版社, 第二章
    http://oreilly.com/catalog/9780596527730/
    http://www.oreilly.com.cn/book.php?bn=978-7-111-25080-7

    [10] 设计模式 - 基于 C# 的工程化实现及扩展, 王翔 着, 电子工业出版社, 第十四章
    http://www.china-pub.com/129880

    [11] Design Patterns: Elements of Reusable Object-Oriented Software
    http://www.amazon.com/exec/obidos/tg/detail/-/0201633612/ref=ase_portlandpatternrA/002-6454224-1040813?v=glance&s=books

    [12] Design Patterns 于 Java 语言上的实习应用 (繁体中文翻译本), 结城浩 着, 博硕文化出版社

    --------------------------------------------------------

  • 相关阅读:
    zbb20181207 springboot @ConfigurationProperties使用
    zbb20181206 logback,lombok 默认日志logback配置解析
    Spring Boot (8) 全局异常处理
    Spring Boot (7) JdbcTemplate访问数据库
    Spring Boot (6) Spring Data JPA
    Spring Boot (4) 静态页面和Thymeleaf模板
    Spring Boot (3) 热部署devtools
    Spring Boot (2) Restful风格接口
    Spring Boot (1) 构建第一个Spring Boot工程
    idea使用maven搭建ssm框架实现登陆商品增删改查
  • 原文地址:https://www.cnblogs.com/WizardWu/p/1517301.html
Copyright © 2011-2022 走看看