代理模式是一种结构型模式,通常源于下边的情况:人们对于复杂的软件系统经常有一种处理手法,即添加一个间接层,从而对系统获得一种更为灵活,满足特定须要的解决方式。比例如以下图中,B有安全控制或者是缓存控制。B中存在A根本不须要知道的控制方式。A直接使用B,结构上复杂,实现也不方便。A直接使用B的方式,控制不够灵活,可能要用到A根本不知道的方式。添加一个间接层,从而对系统获得更为灵活、满足特定须要的解决方式。假如A须要调用B三次,B比方处理远程的另外一个进程,C做为B的代理人。A和C处于一个地址空间,B可能是一个远程的一个软件,C就象一个缓存一样。在某个触发点的时候,再C与B通信。远程代理。不光实现缓存的效果,屏蔽了分布式通信的细节。 



        我们能通过使用代理模式将有效地向client屏蔽细节,减少client与系统模块的耦合度,为一个对象提供一个能够连接或操纵它的代理或接口,是软件设计模式中的一项基本技巧。代理模式通常使用在client无法直接调用代理所指定的对象,比方位于不同主机中的类之间是无法直接调用的,此时就须要建立代理类并通过代理来调用实际的对象。在代理模式中,有两个对象參与处理同一个请求,接受请求的对象将请求托付给还有一个对象来处理,最典型的托付模式是事件处理,由事件源托付给实现了事件监听的对象去处理。托付模式是一项基本技巧,更多的模式,如状态模式、策略模式、訪问者模式本质上是在更特殊的场合採用了托付模式。“托付”在C#中是一个语言级特性,而在Java语言中没有直接的相应,可是我们能够通过动态代理来实现托付!



      我们举几个样例来说明代理模式:(1)人类在改造自然的过程中,会添加非常多间接的工具。比方要挪动一块大石头,我们引入一个间接工具,棍子,仅仅是随着人类进步,棍子变成了千斤顶,铲车。(2)就象记者与明星一样。记者想採訪明星,必须通过经纪人,全部记者全直接联系明星,我预计明星,戏也别拍了,歌也别唱了。记者你不能频繁地与骚扰明星。你想约,什么时候约,在什么地点,有什么不该问的。这些细节问题,经纪人一次性会网罗下来,再与明星协商。记者不须要知道明星的电话号码和其他联系方式,一切由经纪人去代理。(3)操作系统就是一个非常牛的代理,最早的计算机没有软件,没有程序猿,更没有操作系统。添加一些间接的层面。中间软件成为上层软件与硬件。共同的任务,操作系统代理应用软件与硬件。我们就是根本就不知道硬件知识,更加别提机器指令,我们一样通过高层软件驱动硬件工作。(4)直接和数据库打交道非常不好,业务逻辑充斥了SQL代码。所以,金融软件和分布式WEB数据库页面,通常具有中间件来处理前台响应,再适时与后台数据库通信。



       再说到在面向对象中引入代理的动机:在面向对象系统中,有些对象因为某种原因(比方对象创建的开销非常大,或者某些操作须要安全控制,或者须要进程外的訪问等)直接訪问会给使用者、或者系统结构带来非常多麻烦。怎样在不失去透明操作对象的同一时候来管理或控制这些对象特有的复杂性?添加一层间接层是软件开发常见的解决方案。JVM,都是间接层。是软件系统中对许很多多复杂问题的一种常见解决方法。在面向对象系统中,直接使用某些对象会带来非常多问题,作为间接层的proxy对象便 是解决这一问题的经常使用手段。



      详细proxy设计模式的实现方法、实现粒度都相关非常大,有些可能对单个对象做细粒度的控制,假设copy-0n-write技术,有些可能对组件模块提供抽象代理层,在架构层次对对象做proxy,Proxy并不一定要求保持接口的一致性,仅仅要可以实现间接控制,有时候损及一些透明性是可以接受的。下边就是实现的小代码,就是从前台接收一个数字,后台换算成平方,尽管比較幼稚,但能比較浅显地说明道理:



interface Function{

   void f(int a);

}

class BackRun implements Function{

   public void f(int a){

      System.out.println("对前台回应:" + a*a);

   }

}

public class Proxy implements Function{

   private BackRun backRun;

   public Proxy(){

      if(backRun == null)

          backRun = new BackRun();

   }

    public void f(int a){

       System.out.println("開始连接网络连接..");

       System.out.println("连接成功,处理后台方法");

       backRun.f(a);    //完毕代理的使用

    }

}

class ForeRun{

   public static void main(String[] args) {

      int a = 3;

      Function x = new Proxy();

      x.f(a);

   }

}



-----------------------------------------------------------------------------------------

     再分享一个数据库连接池的代理样例吧:

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

import java.sql.Connection;



public class ConnectionHandler implements InvocationHandler {

    private Connection con;

    private connectionPool pool;

    public ConnectionHandler(connectionPool pool){

        this.pool = pool;

    }

    public Connection bind(Connection con){

        this.con = con;

        Connection proxyCon = (Connection)Proxy.newProxyInstance(con.getClass().getClassLoader(),

                con.getClass().getInterfaces(), this);

        return proxyCon;

    }

    public Object invoke(Object arg0, Method arg1, Object[] arg2)

            throws Throwable {

        // TODO Auto-generated method stub

        Object obj = null;

        if("close".equals(arg1.getName())){

            pool.releaseConnection(con);

        }else{

            obj = arg1.invoke(con, arg2);

        }

        return obj;

    }



}   

设计模式之代理模式学习_数据库


     (个人觉得如今编程有滥用继承的趋势,JDK 中 Stack 就是一个滥用继承的典型!Stack继承自Vector,事实上 Stack 与Vector 在用途上全然是风马牛不相及的两个容器。Stack 和 Vector 的功能是不一样的,Stack 是不同意插入数据到 Stack 不论什么位置的,可是 Vector 是能够的,假设 Stack 继承自 Vector,那么这种 Stack 就能够使用 add(int index, E element) 在不论什么位置插入数据,这明显不符合栈的要求。代码编写有个这种原则:能不用继承就不用继承,能使用托付实现的就不使用继承。两个类有明显示的层级关系时使用继承,没有明显的层级关系,不过为了在一个类中使用还有一个类的方法时应该使用托付。例如说swing的事件处理模型就是一种基于托付的模型,即一个事件源产生一个事件并将它法受到一个或多个监听器那里。监听器等待事件,知道收到一个事件。一旦事件被接受,监听器将会处理这个事件,让后返回对应的值。就是代理, PROXY, 是设计模式的一种.。比方struts1的控制流程就是利用的托付,即ActionServlet接到请求后托付给equestProcessor 去处理不同模块的请求,spring,EJB中的动态代理也都是基于此实现。)