Java之 代理模式(Proxy)(七)

2014-11-24 07:48:24 · 作者: · 浏览: 5
根据需要来创建“大”对象,只有到必须创建对象的时候,虚代理才会创建对象,从而大大加快程序运行速度,并节省资源。通过虚代理可以对系统进行优化。
  • 保护代理:可以在访问一个对象的前后,执行很多附加的操作,除了进行权限控制之外,还可以进行很多跟业务相关的处理,而不需要修改被代理的对象。也就是说,可以通过代理来给目标对象增加功能。
  • 智能指引:跟保护代理类似,也是允许在访问一个对象的前后,执行很多附加的操作,这样一来就可以做很多额外的事情,比如:引用计数等。

    11.3.5 思考代理模式

    1:代理模式的本质

    代理模式的本质:控制对象访问。

    代理模式通过代理目标对象,把代理对象插入到客户和目标对象之间,从而为客户和目标对象引入一定的间接性,正是这个间接性,给了代理对象很多的活动空间,代理对象可以在调用具体的目标对象前后,附加很多操作,从而实现新的功能或是扩展目标对象的功能,更狠的是,代理对象还可以不去创建和调用目标对象,也就是说,目标对象被完全代理掉了,或是被替换掉了。

    从实现上看,代理模式主要是使用对象的组合和委托,尤其是在静态代理的实现里面,会看得更清楚。但是也可以采用对象继承的方式来实现代理,这种实现方式在某些情况下,比使用对象组合还要来得简单。

    举个例子来说明一下,改造11.3.2保护代理的例子来说明。

    (1)首先就是去掉OrderApi,现在改成继承的方式实现代理,不再需要公共的接口了

    (2)Order对象变化不大,只是去掉实现的OrderApi接口就好了,示例代码如下:

    public class Order implements OrderApi {

    //其它的代码没有任何变化,就不去赘述了

    }

    (3)再看看代理的实现,变化较多,大致有如下的变化:

    • 不再实现OrderApi,而改成继承Order
    • 不需要再持有目标对象了,因为这个时候父类就是被代理的对象
    • 原来的构造方法去掉,重新实现一个传入父类需要的数据的构造方法
    • 原来转调目标对象的方法,现在变成调用父类的方法了,用super关键字
    • 除了几个被保护代理的setter方法外,不再需要getter方法了

      示例代码如下:

      /**

      * 订单的代理对象

      */

      public class OrderProxy extends Order{

      public OrderProxy(String productName

      ,int orderNum,String orderUser){

      super(productName,orderNum,orderUser);

      }

      public void setProductName(String productName,String user) {

      //控制访问权限,只有创建订单的人员才能够修改

      if(user!=null && user.equals(this.getOrderUser())){

      super.setProductName(productName, user);

      }else{

      System.out.println("对不起"+user

      +",您无权修改订单中的产品名称。");

      }

      }

      public void setOrderNum(int orderNum,String user) {

      //控制访问权限,只有创建订单的人员才能够修改

      if(user!=null && user.equals(this.getOrderUser())){

      super.setOrderNum(orderNum, user);

      }else{

      System.out.println("对不起"+user

      +",您无权修改订单中的订购数量。");

      }

      }

      public void setOrderUser(String orderUser,String user) {

      //控制访问权限,只有创建订单的人员才能够修改

      if(user!=null && user.equals(this.getOrderUser())){

      super.setOrderUser(orderUser, user);

      }else{

      System.out.println("对不起"+user

      +",您无权修改订单中的订购人。");

      }

      }

      public String toString(){

      return "productName="+this.getProductName()+",orderNum="

      +this.getOrderNum()+",orderUser="+this.getOrderUser();

      }

      }

      (4)客户端的变化不大,主要是不再直接面向OrderApi接口,而是使用Order对象了,另外创建代理的构造方法也发生了变化,示例代码如下:

      public class Client {

      public static void main(String[] args) {

      //张三先登录系统创建了一个订单

      Order order = new OrderProxy("设计模式",100,"张三");

      //李四想要来修改,那就会报错

      order.setOrderNum(123, "李四");

      //输出order

      System.out.println("李四修改后订单记录没有变化:"+order);

      //张三修改就不会有问题

      order.setOrderNum(123, "张三");

      //再次输出order

      System.out.println("张三修改后,订单记录:"+order);

      }

      }

      去运行一下,测试看看,体会一下这种实现方式。

      2:何时选用代理模式

      建议在如下情况中,选用代理模式:

      • 需要为一个对象在不同的地址空间提供局部代表的时候,可以使用远程代理
      • 需要按照需要创建开销很大的对象的时候,可以使用虚代理
      • 需要控制对原始对象的访问的时候,可以使用保护代理
      • 需要在访问对象的时候执行一些附加操作的时候,可以使用智能指引代理

        11.3.6 相关模式

        l 代理模式和适配器模式
        这两个模式有一定的相似性,但也有差异。
        这两个模式有相似性,它们都为另一个对象提供间接性的访问,而且都是从自身以外的一个接口向这个对象转发请求。
        但是从功能上,两个模式是不一样的。适配器模式主要用来解决接口之间不匹配的问题,它通常是为所适配的对象提供一个不同的接口;而代理模式会实现和目标对象相同的接口。

        l 代理模式和装饰模式
        这两个模式从实现上相似,但是功能上是不同的。
        装饰模式的实现和保护代理的实现上是类似的,都是在转调其它对象的前后执行一定的功能。但是它们的目的和功能都是不同的。
        装饰模式的目的是为了让你不生成子类就可以给对象添加职责,也就是为了动态的增加功能;而代理模式的主要目的是控制对对象的访问。

        更多设计课程搜索“跟着CC学设计”即可