虛擬代理模式(Virtual Proxy)是一種節省內存的技術,它建議建立那些佔用大量內存或處理複雜的對象時,把建立這類對象推遲到使用它的時候。在特定的應用中,不一樣部分的功能由不一樣的對象組成,應用啓動的時候,不會當即使用全部的對象。在這種狀況下,虛擬代理模式建議推遲對象的建立直到應用程序須要它爲止。對象被應用第一次引用時建立而且同一個實例能夠被重用。這種方法優缺點並存。html
優勢:java
這種方法的優勢是,在應用程序啓動時,因爲不須要建立和裝載全部的對象,所以加速了應用程序的啓動。程序員
缺點:面試
由於不能保證特定的應用程序對象被建立,在訪問這個對象的任何地方,都須要檢測確認它不是空(null)。也就是,這種檢測的時間消耗是最大的缺點。ide
應用虛擬代理模式,須要設計一個與真實對象具備相同接口的單獨對象(指虛擬代理)。不一樣的客戶對象能夠在建立和使用真實對象地方用相應的虛擬對象來代替。虛擬對象把真實對象的引用做爲它的實例變量維護。代理對象不要自動建立真實對象,當客戶須要真實對象的服務時,調用虛擬代理對象上的方法,而且檢測真實對象是否被建立。函數
若是真實對象已經建立,代理把調用轉發給真實對象,若是真實對象沒有被建立:工具
按照這種安排,驗證對象存在和轉發方法調用這些細節對於客戶是不可見的。客戶對象就像和真實對象同樣與代理對象進行交互。所以客戶從檢測真實對象是否爲null中解脫出來,另外,因爲建立代理對象在時間和處理複雜度上要少於建立真實對象。所以,在應用程序啓動的時候,用代理對象代替真實對象初始化。ui
例子:this
假設咱們創建一個JAVA程序的集成開發環境(Integrated Development Environment),這個環境包括三個功能:編譯、運行、生成JavaDoc文檔。在新建和編輯Java程序時,最爲經常使用的是編譯和運行。至於生成JavaDoc文檔對於每個Java程序不是必需的。所以,在Java開發環境啓動時,不要建立和裝載實現集成開發環境所有功能的全部對象,僅建立那些在編輯、編譯、運行時用到的對象,保留提供生成JavaDoc文檔的對象,這是一個好的設計思想。這種對象建立策略可以高效地利用內存空間而且加快了集成開發環境的啓動速度。spa
假設編譯、運行、生成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對象有如下優勢:
在不改變RealProcessor實現的前提下,能夠經過定義IDEOperation的另一個子類ProxyProcessor來實現虛擬代理。由於RealProcessor和ProxyProcessor共享相同的接口,客戶對象能夠用ProxyProcessor代替RealProcessor。圖25.1展現了類層次;
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崗面試題)
原文出處:https://www.cnblogs.com/Java-no-1/p/11347427.html