C#设计模式(13)-Proxy Pattern

转载 2006年06月10日 15:59:00

一、 代理(Proxy)模式

代理(Proxy)模式给某一个对象提供一个代理,并由代理对象控制对原对象的引用。

代理模式的英文叫做Proxy或Surrogate,中文都可译成"代理"。所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。


二、 代理的种类

如果按照使用目的来划分,代理有以下几种:

  • 远程(Remote)代理:为一个位于不同的地址空间的对象提供一个局域代表对象。这个不同的地址空间可以是在本机器中,也可是在另一台机器中。远程代理又叫做大使(Ambassador)。
  • 虚拟(Virtual)代理:根据需要创建一个资源消耗较大的对象,使得此对象只在需要时才会被真正创建。
  • Copy-on-Write代理:虚拟代理的一种。把复制(克隆)拖延到只有在客户端需要时,才真正采取行动。
  • 保护(Protect or Access)代理:控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。
  • Cache代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
  • 防火墙(Firewall)代理:保护目标,不让恶意用户接近。
  • 同步化(Synchronization)代理:使几个用户能够同时使用一个对象而没有冲突。
  • 智能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来等。

在所有种类的代理模式中,虚拟(Virtual)代理、远程(Remote)代理、智能引用代理(Smart Reference Proxy)和保护(Protect or Access)代理是最为常见的代理模式。


三、 远程代理的例子

Achilles是一个用来测试网站的安全性能的工具软件。Achilles相当于位于客户端的的一个桌面代理服务器,在一个HTTP过程里起到一个中间人的作用,但是Achilles与通常的代理服务器又有不同。Achilles截获双向的通信数据,使得Achilles软件的用户可以改变来自和发往网络服务器的数据,甚至可以拦截并修改SSL通讯。(这点在《Java与模式》中解释的不是很清楚,关于对非对称密钥加密拦截、破解方法,可以参考我的另外一篇文章《通过代理截取并修改非对称密钥加密信息》)。

另外一个例子就是Windows的快捷方式。快捷方式是它所引用的程序的一个代理。


四、 代理模式的结构

代理模式的类图如下图所示:

代理模式所涉及的角色有:

抽象主题角色(Subject):声明了真实主题和代理主题的共同接口,这样一来在任何使用真实主题的地方都可以使用代理主题。

代理主题(Proxy)角色:代理主题角色内部含有对真是主题的引用,从而可以在任何时候操作真实主题对象;代理主题角色提供一个与真实主题角色相同的接口,以便可以在任何时候都可以替代真实主体;控制真实主题的应用,负责在需要的时候创建真实主题对象(和删除真实主题对象);代理角色通常在将客户端调用传递给真实的主题之前或之后,都要执行某个操作,而不是单纯的将调用传递给真实主题对象。

真实主题角色(RealSubject)角色:定义了代理角色所代表的真实对象。


五、 代理模式示例性代码

以下示例性代码实现了代理模式:

 

// Proxy pattern -- Structural example  
using System;

// "Subject"
abstract class Subject
{
  
// Methods
  abstract public void Request();
}


// "RealSubject"
class RealSubject : Subject
{
  
// Methods
  override public void Request()
  
{
    Console.WriteLine(
"Called RealSubject.Request()");
  }

}


// "Proxy"
class Proxy : Subject
{
  
// Fields
  RealSubject realSubject;

  
// Methods
  override public void Request()
  
{
    
// Uses "lazy initialization"
    if( realSubject == null )
      realSubject 
= new RealSubject();

    preRequest();
    realSubject.Request();
    postRequest();
  }


  
public void preRequest()
  
{ Console.WriteLine("PreRequest."); }

  
public void postRequest()
  
{ Console.WriteLine("PostRequest."); }
}


/// <summary>
/// Client test
/// </summary>

public class Client
{
  
public static void Main( string[] args )
  
{
    
// Create proxy and request a service
    Proxy p = new Proxy();
    p.Request();
  }

}


六、 高老庄悟空降八戒

尽管那时候八戒还不叫八戒,但为了方便,这里仍然这样称呼他。

高老庄的故事

却说那春融时节,悟空牵着白马,与唐僧赶路西行。忽一日天色将晚,远远地望见一村人,这就是高老庄,猪八戒的丈人高太公家。为了将高家三小姐解救出八戒的魔掌,悟空决定扮做高小姐,会一会这个妖怪:

"行者却弄神通,摇身一变,变得就如那女子一般,独自个坐在房里等那妖精。不多时,一阵风来,真个是走石飞砂……那阵狂风过处,只见半空里来了一个妖精,果然生得丑陋:黑脸短毛,长喙大耳,穿一领青不青、蓝不蓝的梭布直裰,系一条花布手巾……走进房,一把搂住,就要亲嘴……"

高家三小姐的神貌和本人

悟空的下手之处是将高家三小姐的神貌和她本人分割开来,这和"开一闭"原则有异曲同工之妙。这样一来,"高家三小姐本人"也就变成了"高家三小姐神貌"的具体实现,而"高家三小姐神貌"则变成了抽象角色,如下图所示。

悟空扮演并代替高家三小姐

悟空巧妙地实现了"高家三小姐神貌",也就是说同样变成了"高家三小姐神貌"的子类。悟空可以扮演高家三小姐,并代替高家三小姐会见八戒,其静态结构图如下图所示。

悟空代替"高家三小姐本人"去会见猪八戒。显然这就是代理模式的应用。具体地讲,这是保护代理模式的应用。只有代理对象认为合适时,才会将客户端的请求传递给真实主题对象。

八戒分辨不出真假老婆

从《西游记》的描述可以看出,猪八戒根本份辨不出悟空扮演的"高家三小姐替身"和 "高家三小姐本人"。客户端分辨不出代理主题对象与真实主题对象,这是代理模式的一个
重要用意。

悟空代替高家三小姐会见八戒的对象图如下图所示。


七、 不同类型的代理模式

远程代理

可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。客户完全可以认为被代理的对象是局域的而不是远程的,而代理对象承担了大部分的网络通信工作,远程代理的结构图如下图所示。

虚拟代理

使用虚拟代理模式的优点就是代理对象可以在必要的时候才将被代理的对象加载。代理可以对加载的过程加以必要的优化。当一个模块的加载十分耗费资源的时候,虚拟代理的优点就非常明显。

保护代理

保护代理可以在运行时间对用户的有关权限进行检查,然后在核实后决定将调用传递给被代理的对象。

智能引用代理

在访问一个对象时可以执行一些内务处理(Housekeeping)操作,比如计数操作等。


八、 代理模式实际应用的例子

该例子演示了利用远程代理模式提供对另外一个应用程序域(AppDomain)的对象进行访问控制。

 

// Proxy pattern -- Real World example
using System;
using System.Runtime.Remoting;

// "Subject" 
public interface IMath
{
  
// Methods
  double Add( double x, double y );
  
double Sub( double x, double y );
  
double Mul( double x, double y );
  
double Div( double x, double y );
}


// "RealSubject" 
class Math : MarshalByRefObject, IMath
{
  
// Methods
  public double Add( double x, double y )return x + y; }
  
public double Sub( double x, double y )return x - y; }
  
public double Mul( double x, double y )return x * y; }
  
public double Div( double x, double y )return x / y; }
}


// Remote "Proxy Object" 
class MathProxy : IMath
{
  
// Fields
  Math math;

  
// Constructors
  public MathProxy()
  
{
    
// Create Math instance in a different AppDomain
    AppDomain ad = System.AppDomain.CreateDomain("MathDomain",nullnull );
    ObjectHandle o 
= ad.CreateInstance("Proxy_RealWorld""Math"false,
      System.Reflection.BindingFlags.CreateInstance, 
nullnullnull,null,null );
    math 
= (Math) o.Unwrap();
  }


  
// Methods
  public double Add( double x, double y )
  

    
return math.Add(x,y); 
  }

  
public double Sub( double x, double y )
  

    
return math.Sub(x,y); 
  }

  
public double Mul( double x, double y )
  

    
return math.Mul(x,y); 
  }

  
public double Div( double x, double y )
  

    
return math.Div(x,y); 
  }

}

/// <summary>
///   ProxyApp test
/// </summary>

public class ProxyApp
{
  
public static void Main( string[] args )
  
{
    
// Create math proxy
    MathProxy p = new MathProxy();

    
// Do the math
    Console.WriteLine( "4 + 2 = {0}", p.Add( 42 ) );
    Console.WriteLine( 
"4 - 2 = {0}", p.Sub( 42 ) );
    Console.WriteLine( 
"4 * 2 = {0}", p.Mul( 42 ) );
    Console.WriteLine( 
"4 / 2 = {0}", p.Div( 42 ) );
  }

}


 

参考文献:
阎宏,《Java与模式》,电子工业出版社
[美]James W. Cooper,《C#设计模式》,电子工业出版社
[美]Alan Shalloway  James R. Trott,《Design Patterns Explained》,中国电力出版社
[美]Robert C. Martin,《敏捷软件开发-原则、模式与实践》,清华大学出版社
[美]Don Box, Chris Sells,《.NET本质论 第1卷:公共语言运行库》,中国电力出版社

【设计模式】学习笔记15:代理模式(Proxy Pattern)

本笔记内容: 1. JAVA远程代理调用(RMI) 2. 代理模式 走进代理模式 在上一篇的状态模式中,我们实现了一个糖果机GumballMachine, 客户通过投币可以买到糖果. 现在设想这...
  • shuangde800
  • shuangde800
  • 2013年08月26日 00:22
  • 4056

设计模式(结构型)之代理模式(Proxy Pattern)

代理模式是常用的结构型设计模式之一,当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现相同的接口。根据代理模式...
  • yanbober
  • yanbober
  • 2015年05月04日 18:48
  • 5421

设计模式(13)——代理模式(Proxy Pattern)

一、引言 在软件开发过程中,有些对象有时候会由于网络或其他的障碍,以至于不能够或者不能直接访问到这些对象,如果直接访问对象给系统带来不必要的复杂性,这时候可以在客户端和目标对象之间增加一层中间层,让...
  • qq4267002
  • qq4267002
  • 2016年03月03日 11:30
  • 227

我所理解的设计模式(C++实现)——代理模式(Proxy Pattern)

概述 作为C++工程师,免不了要管理内存,内存管理也是C++中的难点,而智能指针采用引用计数的办法很方便的帮我们管理了内存的使用,极大方便了我们的工作效率。而智能指针的这种用法其实就是代理模式的...
  • LCL_data
  • LCL_data
  • 2013年05月29日 14:56
  • 9759

JAVA设计模式之 代理模式【Proxy Pattern】

一、概述     给某一个对象提供一个代理,并由代理对象来完成对原对象的访问。代理模式是一种对象结构型模式。 二、适用场景     当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代...
  • l416112167
  • l416112167
  • 2015年01月10日 16:15
  • 2733

代理模式(Proxy Pattern)- 最易懂的设计模式解析

前言今天我来全面总结一下Android开发中最常用的设计模式 - 代理模式。 其他设计模式介绍 1分钟全面了解“设计模式” 单例模式(Singleton) - 最易懂的设计模式解析 ...
  • carson_ho
  • carson_ho
  • 2017年02月07日 15:34
  • 6163

C#设计模式之代理模式(Proxy Pattern)

一、引言 在软件开发过程中,有些对象有时候会由于网络或其他的障碍,以至于不能够或者不能直接访问到这些对象,如果直接访问对象给系统带来不必要的复杂性,这时候可以在客户端和目标对象之间增加一层中间层...
  • MR_yuan24
  • MR_yuan24
  • 2014年10月25日 22:08
  • 432

C#设计模式之代理模式(Proxy Pattern)

装饰模式解释:         为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。 ...
  • donnie88888888
  • donnie88888888
  • 2016年10月14日 18:41
  • 203

设计模式总结之Proxy Pattern(代理模式)

为其他对象提供一种代理以控制对这个对象的访问。
  • cooldragon
  • cooldragon
  • 2016年08月11日 00:50
  • 1163

设计模式之动态代理(dynamic proxy)

1 动态代理与静态代理我们从上一篇设计模式之代理模式一文中已经知道,在代理模式中代理对象和被代理对象一般实现相同的接口,调用者与代理对象进行交互。代理的存在对于调用者来说是透明的,调用者看到的只是接口...
  • suifeng3051
  • suifeng3051
  • 2016年05月26日 15:16
  • 1876
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C#设计模式(13)-Proxy Pattern
举报原因:
原因补充:

(最多只允许输入30个字)