描述:
計數代理模式在客戶對象調用服務提供者對象上方法的前後執行諸如日志(logging)和計數(counting)一系列附加功能時很有用。計數代理模式建議把這些附加功能封裝在一個單獨的對象,這個對象就是指計數代理對象,而不是把這些附加的功能實現放到服務提供者的內部。良好的對象設計的一個特征就是對象要專注於提供特定的功能。換句話說,理想的對象不應該做各種不相干的事情。把諸如日志(logging)和計數(counting)等類似的功能封裝為一個單獨的對象,而讓服務提供者對象僅提供它自己的特定功能。也就是說,只允許服務提供者對象執行定義良好、特定的任務。
計數代理被設計成可以被客戶訪問的與服務提供者具有相同接口的對象。客戶對象不是直接訪問服務提供者,而是調用計數代理對象上的方法,計數代理執行必要的紀錄日志(logging)和計數(counting)功能後,再把方法調用傳遞給服務提供著對象。如圖1
Figure1: Generic Class Association When the Counting Proxy Pattern Is Applied
下面的例子說明了如何在應用程序中利用計數代理。
例子:
讓我們設計一個Order類,類層次如圖2,OrderIF接口聲明了getAllOrders讀取數據庫中所有訂單的簡單方法。
Figure2: Order Class Hierarchy
public interface OrderIF {
public Vector getAllOrders();
}
作為getAllOrders方法實現的一部分,Order類實用了FileUtil工具類從order.txt文件中讀取訂單項。
public class Order implements OrderIF {
public Vector getAllOrders() {
FileUtil fileUtil = new FileUtil();
Vector v = fileUtil.fileToVector("orders.txt");
return v;
}
}
讓我們假定在調用getAllOrders()時,需要把取數據文件所花費的時間和記錄條數要記錄的log日志文件中。
這個附加的功能可以設計一個單獨的OrderProxy類來實現,它與真實對象Order一樣實現OrderIF接口。這樣保證了OrderProxy對象提供給客戶與真實對象Order一樣的接口。如圖3
Figure3: Order Class Hierarchy with the Counting Proxy
public class OrderProxy implements OrderIF {
private int counter = 0;
public Vector getAllOrders() {
Order order = new Order();
counter++;
long t1 = System.currentTimeMillis ();
Vector v = order.getAllOrders();
long t2 = System.currentTimeMillis();
long timeDiff = t2 ? t1;
String msg = "Iteration=" + counter + "::Time=" + timeDiff + "ms";
//log the message
FileUtil fileUtil = new FileUtil();
fileUtil.writeToFile("log.txt”,msg, true, true);
return v;
}
}
客戶對象MainApp就想調用真實對象Order一樣調用OrderProxy對象上的getAllOrders()方法,OrderProxy對象傳遞這個調用給真實對象Order,計算讀取所有訂單所花費的時間並使用FileUtil幫助類將其紀錄的log日志文件中。在這個過程中,OrderProxy扮演者計數代理的角色。
public class MainApp {
public static void main(String[] args) {
OrderIF order = new OrderProxy();
Vector v = order.getAllOrders();
v = order.getAllOrders();
v = order.getAllOrders();
v = order.getAllOrders();
}
}