Proxy模式解说
在软件系统中,我们无时不在跨越障碍,当我们访问网络上一台计算机的资源时,我们正在跨越网络障碍,当我们去访问服务器上数据库时,我们又在跨越数据库访问障碍,同时还有网络障碍。跨越这些障碍有时候是非常复杂的,如果我们更多的去关注处理这些障碍问题,可能就会忽视了本来应该关注的业务逻辑问题,Proxy模式有助于我们去解决这些问题。我们以一个简单的数学计算程序为例,这个程序只负责进行简单的加减乘除运算:
如果说这个计算程序部署在我们本地计算机上,使用就非常之简单了,我们也就不用去考虑Proxy模式了。但现在问题是这个Math类并没有部署在我们本地,而是部署在一台服务器上,也就是说Math类根本和我们的客户程序不在同一个地址空间之内,我们现在要面对的是跨越Internet这样一个网络障碍:/// <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;
}
}

图3
这时候调用Math类的方法就没有下面那么简单了,因为我们更多的还要去考虑网络的问题,对接收到的结果解包等一系列操作。
为了解决由于网络等障碍引起复杂性,就引出了Proxy模式,我们使用一个本地的代理来替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);
}
}

现在可以说我们已经实现了对Math类的代理,存在的一个问题是我们在MathProxy类中调用了原实现类Math的方法,但是Math并不一定实现了所有的方法,为了强迫Math类实现所有的方法,另一方面,为了我们更加透明的去操作对象,我们在Math类和MathProxy类的基础上加上一层抽象,即它们都实现与IMath接口,示意图如下:/// <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类了:/// <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
{
//
}
到这儿整个使用Proxy模式的过程就完成了,回顾前面我们的解决方案,无非是在客户程序和Math类之间加了一个间接层,这也是我们比较常见的解决问题的手段之一。另外,对于程序中的接口Imath,并不是必须的,大多数情况下,我们为了保持对对象操作的透明性,并强制实现类实现代理类所要调用的所有的方法,我们会让它们实现与同一个接口。但是我们说代理类它其实只是在一定程度上代表了原来的实现类,所以它们有时候也可以不实现于同一个接口。/// <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);
}
}