IOU 设计模式介绍及应用
2010-03-15 00:00:00 来源:WEB开发网双剑合璧:IOU 模式结合 Java 动态代理
鱼和熊掌可否兼得
理想的情况下,用户会希望 IOU 模式下方法的返回类型依然是真实类型。似乎是“鱼和熊掌不可兼得”式的矛盾,因为根据传统的观点,一个方法是无法返回两种类型的(尤其当两种类型又无必然的联系时)。但是,Java 动态代理机制给我们带来了希望(本文假设读者对 Java 动态代理机制已经有所了解,不了解的读者请查阅相关资料)。通过 Java 动态代理机制,我们能够动态地为一组目标接口(允许是任意不相关的接口)创建代理对象,该代理对象将同时实现所有接口。运用在这里,我们就能够创建一个即是 Iou 类型又是目标接口类型的代理对象,所以它能被安全地从 Iou 类型转换到目标接口类型并返回。这样就消除了传统 IOU 模式下方法返回类型的限制,我们称此为扩展 IOU 模式。
扩展 IOU 模式的 Java 实现
Java 动态代理的核心是将代理对象上的方法调用统统分派转发到一个 InvocationHandler 对象上进行处理,为此,我们需要在 RealIouEscrow 基础再实现一个 InvocationHandler 接口。当用户调用目标接口的任何方法时,都会自动转发到 InvocationHandler 接口的 invoke 方法上执行。在 invoke 方法内部,我们可以及时地进行赎回操作以获得真实结果,然后再通过反射调用相应方法来访问真实结果的属性或功能。对调用者而言,进行赎回操作时可能的等待是完全透明的,最终效果完全等价于直接在真实结果上调用某同步方法。RealIouEscrowEx 类实现见清单 7。
清单 7. RealIouEscrowEx 类实现
public class RealIouEscrowEx extends RealIouEscrow implements InvocationHandler
{
// IOU 结果类的类型对象
private Class type;
public RealIouEscrowEx(Class type) throws IllegalArgumentException
{
if( type == null || !type.isInterface() )
{
throw new IllegalArgumentException("Unsupport non-interface type.");
}
this.type = type;
}
public Iou issueIou()
{
// 返回代理对象,该代理对象同时代理类 Iou 接口类型和结果接口类型
return (Iou)Proxy.newProxyInstance(Iou.class.getClassLoader(),
new Class[] {type, Iou.class},
this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
Object obj;
if( method.getDeclaringClass() == Iou.class )
{
// 如果方法来自于 Iou 类声明,则将本 IOU 对象设为反射执行的目标对象
obj = this;
}
else
{
// 调用非 Iou 类的方法,检查此 IOU 对象是否已经终止,未终止则保持等待直至终止
if( !this.closed() )
{
this.standBy();
}
// 赎回结果对象,并设为反射执行的目标对象
obj = this.redeem();
}
// 在目标对象上执行 invoke 调用
return method.invoke(obj, args);
}
}
更多精彩
赞助商链接