描述
计数代理模式在客户对象调用服务提供者对象上方法的前后执行诸如日志(logging)和计数(counting)一系列附加功能时很有用计数代理模式建议把这些附加功能封装在一个单独的对象这个对象就是指计数代理对象而不是把这些附加的功能实现放到服务提供者的内部良好的对象设计的一个特征就是对象要专注于提供特定的功能换句话说理想的对象不应该做各种不相干的事情把诸如日志(logging)和计数(counting)等类似的功能封装为一个单独的对象而让服务提供者对象仅提供它自己的特定功能也就是说只允许服务提供者对象执行定义良好特定的任务
计数代理被设计成可以被客户访问的与服务提供者具有相同接口的对象客户对象不是直接访问服务提供者而是调用计数代理对象上的方法计数代理执行必要的纪录日志(logging)和计数(counting)功能后再把方法调用传递给服务提供着对象如图
Figure: Generic Class Association When the Counting Proxy Pattern Is Applied
下面的例子说明了如何在应用程序中利用计数代理
例子
让我们设计一个Order类类层次如图OrderIF接口声明了getAllOrders读取数据库中所有订单的简单方法
Figure: Order Class Hierarchy
public interface OrderIF {
public Vector getAllOrders();
}
作为getAllOrders方法实现的一部分Order类实用了FileUtil工具类从ordertxt文件中读取订单项
public class Order implements OrderIF {
public Vector getAllOrders() {
FileUtil fileUtil = new FileUtil();
Vector v = fileUtilfileToVector(orderstxt);
return v;
}
}
让我们假定在调用getAllOrders()时需要把取数据文件所花费的时间和记录条数要记录的log日志文件中
这个附加的功能可以设计一个单独的OrderProxy类来实现它与真实对象Order一样实现OrderIF接口这样保证了OrderProxy对象提供给客户与真实对象Order一样的接口如图
Figure: Order Class Hierarchy with the Counting Proxy
public class OrderProxy implements OrderIF {
private int counter = ;
public Vector getAllOrders() {
Order order = new Order();
counter++;
long t = SystemcurrentTimeMillis ();
Vector v = ordergetAllOrders();
long t = SystemcurrentTimeMillis();
long timeDiff = t ? t;
String msg = Iteration= + counter + ::Time= + timeDiff + ms;
//log the message
FileUtil fileUtil = new FileUtil();
fileUtilwriteToFile(logtxtmsg 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 = ordergetAllOrders();
v = ordergetAllOrders();
v = ordergetAllOrders();
v = ordergetAllOrders();
}
}