在软件系统中,有些对象有时候由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),如果直接访问会给使用者或者系统结构带来很多麻烦,这时可以在客户程序和目标对象之间增加一层中间层,这个中间层就是代理。

    代理模式的定义:给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。

代理模式可分为以下几类:

(1)远程代理:为一个位于不同的地址空间的对象提供一个局域代表对象。好处是系统可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。

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

(3)虚拟代理:根据需要创建一个资源消耗较大的对象,使得此对象只在需要时才会被真正创建。好处是代理对象可以在必要的时候才将被代理的对象加载。

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

这里给出两个使用该模式的例子:

应用一:虚拟代理

例如:word文档打开

Word文档通常会含有链接、图片、表格等对象,但是并不是每次刚打开word时都要创建和实例化这些对象,特别是实例化图片对象很消耗资源。事实上,我们没必要实例化所有图片,当我们在查看word时,每次只是看到其中的一部分,所以没有必要实例化所有资源,可以使用一个虚代理物件,代替图片被载入,来加快打开文档速度,当我们看下一页时再载入图片也不迟。

类图如图所示:

如上图所示,当文档被开启时, ProxyImage代理代替RealImage物件被载入,在还没卷动至图片显示处时,也就是还没有调用 ProxyImage的Draw()时,图片并不会被载入,因而可以加速文档的开启;如果需要显示图片了, ProxyImage的 Draw()会被调用,而这时才真正创建RealImage物件,以从硬盘中载入图片。

主要类代码:

 

public interface Image //Image公共接口

 {

     public abstract void Draw();

 }

//ProxyImage类实现Image接口

public class ProxyImage implements Image

{

     private RealImage realimage;

public void Draw()

{

    If(realimage==NULL)

{

    Realimage=new RealImage();

}

realimage.Draw();

}

 }

//RealImage类实现Image接口

public class RealImage implements Image

 {

public void Draw()

{ Console.WriteLine(“载入图片……”);}

 }

主程序

public class App

 {

     public static void Main()

     {

         ProxyImage proxy = new ProxyImage();

         proxy.Draw();

     }

 }

 

应用二:远程访问

例子:远程数学运算访问

本地客户程序需要调用远程服务器提供的数学运算服务,也就是说数学运算服务和客户程序不在同一个地址空间之内,我们现在要面对的是跨越Internet这样一个网络障碍:这时候调用数学运算服务就没有下面那么简单了,因为我们更多的还要去考虑网络的问题,对接收到的结果解包等一系列操作。为了避免由于网络等障碍引起的复杂性,引用Proxy模式,用一个本地的代理来代替远程数学运算类打点一切,即为我们的系统引入了一层间接层,示意图如下

设计的类图如下:

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

主要代码:

View Code
public interface Math //Math公共接口

 {

     public abstract double Add(double x,double y);

     public abstract double Sub(double x,double y);

     public abstract double Mul(double x,double y);

     public abstract double Dev(double x,double y);

 }

public class ProxyMath implements Math //Proxy类,继承于Math

 {

     private RealMath realmath = new RealMath();

     //Proxy类中不光有调用Math类的方法,还包含一些网络通信,与远程服务器交换数据,此处省略。

     public double Add(double x,double y)

     {

         return math.Add(x,y);

     }

     public double Sub(double x,double y)

     {

         return realmath.Sub(x,y);

     }

     public double Mul(double x,double y)

     {

         return realmath.Mul(x,y);

     }

     public double Dev(double x,double y)

     {

         return realmath.Dev(x,y);

     }

 }

public class RealMath implements 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;

     }

 }

测试主程序

public class App

 {

     public static void Main()

     {

         ProxyMath proxy = new ProxyMath();

         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模式的工作原理:

首先,代理并不改变主题的接口,因为模式的用意是不让客户端感觉到代理的存在;其次,代理使用委派将客户端的调用委派给真实的主题对象,换言之,代理起到的是一个传递请求的作用;第三,代理在传递请求之前和之后都可以执行特定的操作(如网络通信、检查对象是否存在等),而不是单纯传递请求。

posted on 2012-12-25 09:46  Yogurshine  阅读(430)  评论(0编辑  收藏  举报