虚拟代理模式(Virtual Proxy)是一种节省内存的技术,它建议创建那些占用大量内存或处理复杂的对象时,把创建这类对象推迟到使用它的时候。在特定的应用中,不同部分的功能由不同的对象组成,应用启动的时候,不会立即使用所有的对象。在这种情况下,虚拟代理模式建议推迟对象的创建直到应用程序需要它为止。对象被应用第一次引用时创建并且同一个实例可以被重用。这种方法优缺点并存。

优点:

这种方法的优点是,在应用程序启动时,由于不需要创建和装载所有的对象,因此加速了应用程序的启动。

缺点:

因为不能保证特定的应用程序对象被创建,在访问这个对象的任何地方,都需要检测确认它不是空(null)。也就是,这种检测的时间消耗是最大的缺点。

应用虚拟代理模式,需要设计一个与真实对象具有相同接口的单独对象(指虚拟代理)。不同的客户对象可以在创建和使用真实对象地方用相应的虚拟对象来代替。虚拟对象把真实对象的引用作为它的实例变量维护。代理对象不要自动创建真实对象,当客户需要真实对象的服务时,调用虚拟代理对象上的方法,并且检测真实对象是否被创建。

如果真实对象已经创建,代理把调用转发给真实对象,如果真实对象没有被创建:

  1. 代理对象创建真实对象
  2. 代理对象把这个对象分配给引用变量。
  3. 代理把调用转发给真实对象

按照这种安排,验证对象存在和转发方法调用这些细节对于客户是不可见的。客户对象就像和真实对象一样与代理对象进行交互。因此客户从检测真实对象是否为null中解脱出来,另外,由于创建代理对象在时间和处理复杂度上要少于创建真实对象。因此,在应用程序启动的时候,用代理对象代替真实对象初始化。

例子:

假设我们建立一个JAVA程序的集成开发环境(Integrated Development Environment),这个环境包括三个功能:编译、运行、生成JavaDoc文档。在新建和编辑Java程序时,最为常用的是编译和运行。至于生成JavaDoc文档对于每一个Java程序不是必需的。因此,在Java开发环境启动时,不要创建和装载实现集成开发环境全部功能的所有对象,仅创建那些在编辑、编译、运行时用到的对象,保留提供生成JavaDoc文档的对象,这是一个好的设计思想。这种对象创建策略能够高效地利用内存空间并且加快了集成开发环境的启动速度。

假设编译、运行、生成JavaDoc文档这些功能分别由三个工具类提供??Compiler、Runtime和JavaDoc。客户对象可以访问的不同IDE操作的接口以抽象类IDEOperation的形式定义。

public abstract class IDEOperation {
     private Compiler cmp;
     private Runtime rtime;
     public void compile(String javaFile) {
          cmp.compile(javaFile);
         
    }
     public void run(String classFile) {
          rtime.run (classFile);
         
    }
     //to be delayed until needed.
     public abstract void generateDocs(String javaFile);
     public IDEOperation() {
          cmp = new Compiler();
          rtime = new Runtime();
         
    }
}

类IDEOperation提供了编译、运行java程序方法的实现,作为它构造函数的一部分,IDEOperation创建和装载了进行编译和执行操作的Compiler和Runtime对象。生成JavaDoc文档的方法generateDocs方法被设计成抽象的方法,由它的子类来实现。

让我们定义抽象类IDEOperation的一个具体子类RealProcessor。作为RealProcessor构造函数的一部分,创建JavaDoc对象来提供生成JavaDoc文档的服务,通过使用JavaDoc对象功能实现generateDocs方法。

public class RealProcessor extends IDEOperation {
     JavaDoc jdoc;
     public RealProcessor() {
          super();
          jdoc = new JavaDoc();
         
    }
     public void generateDocs(String javaFile) {
          jdoc.generateDocs(javaFile);
         
    }
}

通过上面的实现,RealProcessor类包含了编译、运行和生成JavaDoc文档的所有功能。像我们原来讨论的,生成JavaDoc文档的功能不是每一个Java程序所必须的,当RealProcessor实例化的时候,包括负责生成JavaDoc文档的JavaDoc对象的一系列对象被创建。推迟创建JavaDoc对象有以下优点:

  1. 加速了RealProcessor对象的创建时间,因为它的构造函数创建的很少的对象。
  2. 高效地利用内存,因为在不需要对象服务的时候,不需要把对象保持在内存中。

在不改变RealProcessor实现的前提下,可以通过定义IDEOperation的另外一个子类ProxyProcessor来实现虚拟代理。因为RealProcessor和ProxyProcessor共享相同的接口,客户对象可以用ProxyProcessor代替RealProcessor。图25.1展示了类层次;

Figure 25.1: IDEOperation Class Hierarchy
public class ProxyProcessor extends IDEOperation {
     private RealProcessor realProcessor;
     public void generateDocs(String javaFile) {
          
        /*
  In order to generate javadocs
  the proxy loads the actual object and
  invokes its methods.
  */
          if (realProcessor == null) {
               realProcessor = new RealProcessor();
              
        }
          realProcessor.generateDocs(javaFile);
         
    }
}

作为自己的实例变量,ProxyProcessor维护了RealProcessor对象的一个引用。作为generateDocs方法的一部分,ProxyProcessor检测引用变量是否被初始化为RealProcessor对象。如果没有被初始化,它创建一个RealProcessor对象并把这个对象分配给它的实例变量。一旦RealProcessor对象已经被创建,就调用其上的generateDocs方法。

实际上,也就是当客户对象第一次请求产生javadoc文档时,RealProcessor才被初始化装入内存中。反过来,直到客户需要为Java程序生成javadocs时,JavaDoc对象才会被创建和装入内存中。

客户对象像调用真实处理对象一样调用ProxyProcessor上的方法,并不需要关心(知道)RealProcessor对象是否存在。 至于验证、检测和ProxyProcessor和RealProcessor之间的交互、这样的细节对于客户对象是透明的。

public class Client {
     public static void main(String[] args) {
          
        /*
  At this point objects required for
  the compile and run operations are
  created, but not the objects that provide the
  generate Javadoc functionality.
  */
          IDEOperation IDE = new ProxyProcessor();
          IDE.compile("test.java");
          IDE.run("test.class");
          
        /*
  The Javadoc functionality is accessed
  For the first time and hence the
  Object offering the Javadoc generation
  Functionality is loaded at this point.
  */
          IDE.generateDocs("test.java");
         
    }
}

【推荐阅读】

Java程序员备战“金九银十”必备的面试技巧(附携程Java岗面试题)

阿里架构师浅析Java设计模式之虚拟代理模式的更多相关文章

  1. java设计模式之Proxy(代理模式)

    java设计模式之Proxy(代理模式) 2008-03-25 20:30 227人阅读 评论(0) 收藏 举报 设计模式javaauthorizationpermissionsstringclass ...

  2. Java设计模式之《代理模式》及应用场景

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6525527.html 代理模式算是我接触较早的模式,代理就是中介,中间人.法律上也有代理, ...

  3. 重学 Java 设计模式:实战代理模式「模拟mybatis-spring中定义DAO接口,使用代理类方式操作数据库原理实现场景」

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 难以跨越的瓶颈期,把你拿捏滴死死的! 编程开发学习过程中遇到的瓶颈期,往往是由于看不 ...

  4. Java设计模式学习记录-代理模式

    代理模式 代理模式是常见设计模式的一种,代理模式的定义是:为其他对象提供一种代理以控制对这个对象的访问. 在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起 ...

  5. Java设计模式:Proxy(代理)模式

    概念定义 代理模式是一种使用代理对象来执行目标对象的方法并在代理对象中增强目标对象方法的一种设计模式. 使用代理模式的原因有: 中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象, ...

  6. 《Java设计模式》之代理模式 -Java动态代理(InvocationHandler) -简单实现

    如题 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式可细分为如下, 本文不做多余解释 远程代理 虚拟代理 缓冲代理 保护代理 借鉴文章 ht ...

  7. Java设计模式9:代理模式

    代理模式 代理模式的定义很简单:给某一对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式的结构 有些情况下,一个客户不想活着不能够直接引用一个对象,可以通过代理对象在客户端和目标对象之间 ...

  8. java设计模式-----11、代理模式

    Proxy模式又叫做代理模式,是构造型的设计模式之一,它可以为其他对象提供一种代理(Proxy)以控制对这个对象的访问. 所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代 ...

  9. Java设计模式—Proxy动态代理模式

    代理:设计模式 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 图 1. 代 ...

随机推荐

  1. C语言学习推荐《C语言参考手册(原书第5版)》下载

  2. Java项目案例之--封装的实例

    Java项目案例之---封装的实例 有一个专业类,有一个专业对象,专业名称:计算机科学与技术,专业编号:J001,专业年限:4,对年限添加约束,如果输入小于0,则默认为0,否则显示输入的值 有一个学生 ...

  3. springboot与springcloud的关系

    1 . 问题描述 随着springboot.springcloud的不断迭代升级,开发效率不断提升,越来越多的开发团队加入到spring的大军中,今天用通俗的语言,介绍下什么是springboot,s ...

  4. IQueryable.Where中动态生成多个并或筛选Expression<Func<T, bool>>

    直接上图

  5. grep -nr "Base64Decode" * 查找含有某字符的文件

    grep -nr "Base64Decode" * 查找含有某字符的文件

  6. [leetcode] 51. N-Queens (递归)

    递归,经典的八皇后问题. 利用一位数组存储棋盘状态,索引表示行,值为-1表示空,否则表示列数. 对行进行搜索,对每一行的不同列数进行判断,如果可以摆放符合规则,则摆放,同时遍历下一行. 遍历过程中,若 ...

  7. 利用TCP协议,实现基于Socket的小聊天程序(初级版)

    TCP TCP (Transmission Control Protocol)属于传输层协议.其中TCP提供IP环境下的数据可靠传输,它提供的服务包括数据流传送.可靠性.有效流控.全双工操作和多路复用 ...

  8. linux初学者-磁盘阵列篇

    linux初学者-磁盘阵列篇 在磁盘的使用中,有时候需要提高磁盘的读写数据速度,就要用到磁盘组——raid,也就是磁盘阵列. 磁盘阵列是由最少两块以上的磁盘组成的,raid有许多模式,在这里将介绍其中 ...

  9. storm学习路线指南

    关于对storm的介绍已经有很多了,我这里不做过多的介绍,我介绍一下我自己的学习路线,希望能帮助一些造轮子的同学走一些捷径,毕竟我也是站在前人总结整理的基础上学习了,如果有不足之处,还请大家不要喷我. ...

  10. Windows+Apache+Python+Django 踩坑记录

    摘要 使用Python进行Web项目开发:相对于主流三大Web端解决方案(Java/.NET/PHP) Python在某些方面具有一定的优势,相对 Java/.NET 有更轻量级的部署方案,相对PHP ...