虛擬代理模式(Virtual Proxy)是一種節省內存的技術
它建議創建那些占用大量內存或處理復雜的對象時
把創建這類對象推遲到使用它的時候
在特定的應用中
不同部分的功能由不同的對象組成
應用啟動的時候
不會立即使用所有的對象
在這種情況下
虛擬代理模式建議推遲對象的創建直到應用程序需要它為止
對象被應用第一次引用時創建並且同一個實例可以被重用
這種方法優缺點並存
優點 這種方法的優點是
在應用程序啟動時
由於不需要創建和裝載所有的對象
因此加速了應用程序的啟動
缺點: 因為不能保證特定的應用程序對象被創建
在訪問這個對象的任何地方
都需要檢測確認它不是空(null)
也就是
這種檢測的時間消耗是最大的缺點
應用虛擬代理模式
需要設計一個與真實對象具有相同接口的單獨對象(指虛擬代理)
不同的客戶對象可以在創建和使用真實對象地方用相應的虛擬對象來代替
虛擬對象把真實對象的引用作為它的實例變量維護
代理對象不要自動創建真實對象
當客戶需要真實對象的服務時
調用虛擬代理對象上的方法
並且檢測真實對象是否被創建
如果真實對象已經創建
代理把調用轉發給真實對象
如果真實對象沒有被創建 )代理對象創建真實對象
)代理對象把這個對象分配給引用變量
)代理把調用轉發給真實對象
按照這種安排
驗證對象存在和轉發方法調用這些細節對於客戶是不可見的
客戶對象就像和真實對象一樣與代理對象進行交互
因此客戶從檢測真實對象是否為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) {
pile(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對象的創建時間
因為它的構造函數創建的很少的對象
)高效地利用內存
因為在不需要對象服務的時候
不需要把對象保持在內存中
在不改變RealProcessor實現的前提下
可以通過定義IDEOperation的另外一個子類ProxyProcessor來實現虛擬代理
因為RealProcessor和ProxyProcessor共享相同的接口
客戶對象可以用ProxyProcessor代替RealProcessor
圖
展示了類層次
Figure : 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();
pile(
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
);
}
}
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27581.html