技术开发 频道

结构型模式篇-代理模式(Proxy Pattern)


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类打点一切,即为我们的系统引入了一层间接层,示意图如下



/// <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,并不是必须的,大多数情况下,我们为了保持对对象操作的透明性,并强制实现类实现代理类所要调用的所有的方法,我们会让它们实现与同一个接口。但是我们说代理类它其实只是在一定程度上代表了原来的实现类,所以它们有时候也可以不实现于同一个接口。










0
相关文章