參考文獻:《Java程序性能優化》.葛一鳴
代理模式也是一種常見的設計模式。它使用代理對象完成用戶請求,屏蔽用戶對真實對象的訪問。該模式下,用戶只和代理打交道,而代理需要有當事人的授權,而且一些核心問題需要請示當事人。
代理模式應用很廣泛,包括安全訪問,遠程調用,以及延時加載等,這裏主要講一下如何實現延時加載。
以一個簡單的示例來闡述一下代理模式實現延時加載的方法和意義。假設某客戶端軟件,有根據用戶請求,去查詢數據庫的功能。在查詢數據庫之前,需要獲得數據庫連接,軟件開啓的時候,初始化系統的所有類,此時嘗試獲取數據庫連接。當系統有大量的類似操作時(比如XML解析等),所有這些初始化操作的疊加會使得系統的啓動速度變得非常緩慢。爲此,採用代理模式,採用代理類,封裝對數據庫查詢中的初始化操作,當系統啓動時,初始化這個代理類,而非真實的數據庫查詢類,而代理類什麼都沒有做,因此它的構造是相當迅速的。
在系統啓動時,講消耗資源最多的方法都使用代理模式分離,就可以加快系統的啓動速度,減少用戶的等待時間,而在用戶真正做查詢操作時,再由代理類單獨去加載真實的數據庫查詢類,完成用戶的請求。這個過程就是使用代理模式實現了延時加載。
代理模式的核心思想是:如果當前並沒有使用這個組件,則不需要真實的初始化它,使用一個代理類對象替代他原有的位置,只要在真正使用的時候,纔對它進行加載。
package com.smf.proxy;
/**
* @author 作者SMF:
* @version 創建時間:2018年9月26日 上午10:15:37
* 類說明
*/
public interface IDBQuery {
String request();
}
IDBQuery是一個主題接口,定義代理類和真實類需要對外部提供的服務。
package com.smf.proxy;
/**
* @author 作者SMF:
* @version 創建時間:2018年9月26日 上午10:16:19
* 類說明
*/
public class DBQuery implements IDBQuery{
public DBQuery(){
try {//比較重量級初始化時間比較長
Thread.sleep(10000);
} catch(InterruptedException e){
e.printStackTrace();
}
}
@Override
public String request () {
// TODO Auto-generated method stub
return null;
}
}
DBQuery是真實的查詢類,比較重量級,初始化時間比較長,代理類DBQueryProxy是輕量級對象創建很快,用於代替DBQuery的位置
package com.smf.proxy;
/**
* @author 作者SMF:
* @version 創建時間:2018年9月26日 上午10:38:05
* 類說明
*/
public class DBQueryProxy implements IDBQuery{
private DBQuery real = null;
@Override
public String request () {
//在真實需要的時候才創建真實對象,創建過程可能很慢
if(real==null){
real = new DBQuery();
}
return real.request();
}
}
主函數如下:
package com.smf.proxy;
/**
* @author 作者SMF:
* @version 創建時間:2018年9月26日 上午11:19:32
* 類說明
*/
public class Main {
public static void main(String args[]){
IDBQuery query = new DBQueryProxy();
query.request();
}
}
動態代理介紹:
動態代理是指在運行時動態生成代理類。即,代理類的字節碼將在運行時生成並載入當前的ClassLoader。和靜態代理類相比,動態代理類有很多好處,首先不需要爲真實主題寫一個形式上完全一樣的封裝類,假如主題接口中的方法很多,爲每一個接口寫一個代理方法也是非常煩人的。如果接口有變動,則真實主題和代理類都需要修改,不利於系統維護;其次使用動態代理類的生成方法甚至可以在運行時制定代理類的執行邏輯,從而大大提升系統的靈活性。
詳情見下一篇博客。