介绍一下代理模式(Proxy) - TOMMYHU - 专注互联网开发及运营技术,提供相关资料及软件下载,奇趣网络时事评论!
May 13

介绍一下代理模式(Proxy) 不指定

当我们需要使用的对象很复杂或者需要很长时间去构造,这时就可以使用代理模式(Proxy)。例如:如果构建一个对象很耗费时间和计算机资源,代理模式(Proxy)允许我们控制这种情况,直到我们需要使用实际的对象。一个代理(Proxy)通常包含和将要使用的对象同样的方法,一旦开始使用这个对象,这些方法将通过代理(Proxy)传递给实际的对象。 一些可以使用代理模式(Proxy)的情况:  一个对象,比如一幅很大的图像,需要载入的时间很长。  一个需要很长时间才可以完成的计算结果,并且需要在它计算过程中显示中间结果  一个存在于远程计算机上的对象,需要通过网络载入这个远程对象则需要很长时间,特别是在网络传输高峰期。  一个对象只有有限的访问权限,代理模式(Proxy)可以验证用户的权限  代理模式(Proxy)也可以被用来区别一个对象实例的请求和实际的访问,例如:在程序初始化过程中  可能建立多个对象,但并不都是马上使用,代理模式(Proxy)可以载入需要的真正的对象。  这是一个需要载入和显示一幅很大的图像的程序,当程序启动时,就必须确定要显示的图像,但是实际的图像只能在完全载入后才可以显示!这时我们就可以使用代理模式(Proxy)。  这个代理模式(Proxy)可以延迟实际图像的载入,直到它接收到一个paint请求。在实际图像的载入期间我们可以通过代理模式(Proxy)在实际图像要显示的位置预先载入一个比较小、简单的图形。  图像Proxy代码:总结: 这只是一个很简单的例子(例子来自于《c#设计模式》),通过这个例子可以对代理(Proxy)有初步的认识!Adapter模式和代理模式(Proxy)都是在对象间构造一个简单的层。然而,Adapter模式向对象提供一个不同的接口,代理模式(Proxy)为对象提供相同的接口

代理模式(Proxy Pattern

——.NET设计模式系列之十四

Terrylee20065

摘要:在软件系统中,有些对象有时候由于跨越网络或者其他的障碍,而不能够或者不想直接访问另一个对象,如果直接访问会给系统带来不必要的复杂性,这时候可以在客户程序和目标对象之间增加一层中间层,让代理对象来代替目标对象打点一切。这就是本文要说的Proxy模式。

 

主要内容

1.例说Proxy模式

2Proxy模式效果及实现要点

……

 

概述

在软件系统中,有些对象有时候由于跨越网络或者其他的障碍,而不能够或者不想直接访问另一个对象,如果直接访问会给系统带来不必要的复杂性,这时候可以在客户程序和目标对象之间增加一层中间层,让代理对象来代替目标对象打点一切。这就是本文要说的Proxy模式。

意图

为其他对象提供一种代理以控制对这个对象的访问。

结构图

 Proxy模式结构图

 

生活中的例子

代理模式提供一个中介以控制对这个对象的访问。一张支票或银行存单是账户中资金的代理。支票在市场交易中用来代替现金,并提供对签发人账号上资金的控制。

 

2  使用银行存单例子的Proxy模式对象图

Proxy模式解说

在软件系统中,我们无时不在跨越障碍,当我们访问网络上一台计算机的资源时,我们正在跨越网络障碍,当我们去访问服务器上数据库时,我们又在跨越数据库访问障碍,同时还有网络障碍。跨越这些障碍有时候是非常复杂的,如果我们更多的去关注处理这些障碍问题,可能就会忽视了本来应该关注的业务逻辑问题,Proxy模式有助于我们去解决这些问题。我们以一个简单的数学计算程序为例,这个程序只负责进行简单的加减乘除运算:

/// <summary>

/// Author : Terrylee

/// From : 
http://terrylee.cnblogs.com

/// </summary>

public class Math
{
    
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 Dev(double x,double y)
    
{
        
return x / y;
    }

}

如果说这个计算程序部署在我们本地计算机上,使用就非常之简单了,我们也就不用去考虑Proxy模式了。但现在问题是这个Math类并没有部署在我们本地,而是部署在一台服务器上,也就是说Math类根本和我们的客户程序不在同一个地址空间之内,我们现在要面对的是跨越Internet这样一个网络障碍:

3

这时候调用Math类的方法就没有下面那么简单了,因为我们更多的还要去考虑网络的问题,对接收到的结果解包等一系列操作。

/// <summary>

/// Author : Terrylee

/// From : http://terrylee.cnblogs.com

/// </summary>


public class App
{
    
public static void Main()
    
{
        Math math 
= new Math();

        
// 对接收到的结果数据进行解包

        
double addresult = math.Add(2,3);

        
double subresult = math.Sub(2,3);

        
double mulresult = math.Mul(2,3);

        
double devresult = math.Dev(2,3);
    }

}

为了解决由于网络等障碍引起复杂性,就引出了Proxy模式,我们使用一个本地的代理来替Math类打点一切,即为我们的系统引入了一层间接层,示意图如下

4

我们在MathProxy中对实现Math数据类的访问,让MathProxy来代替网络上的Math类,这样我们看到MathProxy就好像是本地Math类,它与客户程序处在了同一地址空间内:

 

/// <summary>

/// Author : Terrylee

/// From : http://terrylee.cnblogs.com

/// </summary>


public class MathProxy
{
    
private Math math = new Math();

    
// 以下的方法中,可能不仅仅是简单的调用Math类的方法

    
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 Dev(double x,double y)
    
{
        
return math.Dev(x,y);
    }

}

现在可以说我们已经实现了对Math类的代理,存在的一个问题是我们在MathProxy类中调用了原实现类Math的方法,但是Math并不一定实现了所有的方法,为了强迫Math类实现所有的方法,另一方面,为了我们更加透明的去操作对象,我们在Math类和MathProxy类的基础上加上一层抽象,即它们都实现与IMath接口,示意图如下:

示意性代码如下:

 

/// <summary>

/// Author : Terrylee

/// From : http://terrylee.cnblogs.com

/// </summary>


public interface IMath
{
    
double Add(double x,double y);

    
double Sub(double x,double y);

    
double Mul(double x,double y);

    
double Dev(double x,double y);
}


Math类和MathProxy类分别实现IMath接口:

public class MathProxy : IMath
{
    
//
}


public class Math : IMath
{
    
//
}

此时我们在客户程序中就可以像使用Math类一样来使用MathProxy类了:

 

/// <summary>

/// Author : Terrylee

/// From : http://terrylee.cnblogs.com

/// </summary>


public class App
{
    
public static void Main()
    
{
        MathProxy proxy 
= new MathProxy();

        
double addresult = proxy.Add(2,3);

        
double subresult = proxy.Sub(2,3);

        
double mulresult = proxy.Mul(2,3);

        
double devresult = proxy.Dev(2,3);
    }

}

到这儿整个使用Proxy模式的过程就完成了,回顾前面我们的解决方案,无非是在客户程序和Math类之间加了一个间接层,这也是我们比较常见的解决问题的手段之一。另外,对于程序中的接口Imath,并不是必须的,大多数情况下,我们为了保持对对象操作的透明性,并强制实现类实现代理类所要调用的所有的方法,我们会让它们实现与同一个接口。但是我们说代理类它其实只是在一定程度上代表了原来的实现类,所以它们有时候也可以不实现于同一个接口。

效果及实现要点

Proxy模式根据种类不同,效果也不尽相同:

1.远程(Remote)代理:为一个位于不同的地址空间的对象提供一个局域代表对象。这个不同的地址空间可以是在本机器中,也可是在另一台机器中。远程代理又叫做大使(Ambassador)。好处是系统可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。客户完全可以认为被代理的对象是局域的而不是远程的,而代理对象承担了大部份的网络通讯工作。由于客户可能没有意识到会启动一个耗费时间的远程调用,因此客户没有必要的思想准备。

2.虚拟(Virtual)代理:根据需要创建一个资源消耗较大的对象,使得此对象只在需要时才会被真正创建。使用虚拟代理模式的好处就是代理对象可以在必要的时候才将被代理的对象加载;代理可以对加载的过程加以必要的优化。当一个模块的加载十分耗费资源的情况下,虚拟代理的好处就非常明显。

3Copy-on-Write代理:虚拟代理的一种。把复制(克隆)拖延到只有在客户端需要时,才真正采取行动。

4.保护(Protect or Access)代理:控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。保护代理的好处是它可以在运行时间对用户的有关权限进行检查,然后在核实后决定将调用传递给被代理的对象。

5Cache代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。

6.防火墙(Firewall)代理:保护目标,不让恶意用户接近。

7.同步化(Synchronization)代理:使几个用户能够同时使用一个对象而没有冲突。

8.智能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来等。

总结

在软件系统中,增加一个中间层是我们解决问题的常见手法,这方面Proxy模式给了我们很好的实现。

 

参考资料

Erich Gamma等,《设计模式:可复用面向对象软件的基础》,机械工业出版社

Robert C.Martin,《敏捷软件开发:原则、模式与实践》,清华大学出版社

阎宏,《Java与模式》,电子工业出版社

Alan Shalloway James R. Trott,《Design Patterns Explained》,中国电力出版社

MSDN WebCast C#面向对象设计模式纵横谈(13)Proxy代理模式(结构型模式)

http://www.cnblogs.com/images/cnblogs_com/Terrylee/147338/o_info.png); background-attachment: scroll; background-origin: initial; background-clip: initial; background-color: rgb(255, 254, 254); font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; line-height: 24px; text-align: left; background-position: 1% 50%; background-repeat: no-repeat no-repeat; ">作者:TerryLee
出处:http://terrylee.cnblogs.com 
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。


▲返回顶部
Last modified by tommyhu on2012/05/13 16:47

Add a comment

Nickname

emotemotemotemotemotemotemotemotemotemotemotemotemotemotemotemot