如果被装饰的对象实现了其他接口(interface)的不同组合,如何在不丢失额外接口(interface)方法的情况下实现装饰器?例如,假设我们有以下类和接口(interface),其中 I 是我们关心的装饰器,D 是装饰器的实现:
class C1 implements I, I1, I2
class C2 implements I, I2, I3
class C3 implements I, I3, I4
class D implements I {
I wrappedValue
// Methods for I
}
一旦我们用包装的 I(可能是 C1、C2 或 C3)实例化 D 的实例,我们就无法访问包装的 I 可能实现的 I1、I2、I3 和 I4 的其他方法。
最佳答案
如果 C1、C2、C3 是接口(interface),就会有代理解决方案。
interface C1 extends I, I1, I2
否则你需要一个像 cglib 这样的库装饰类(class)。
代理与通用工厂方法相结合将保留其他接口(interface),因此您无需在代码中进行强制转换:
class D<T_I extends I> implements InvocationHandler, I {
public static <T_I extends I> T_I decorate(T_I wrappedValue) {
return (T_I)Proxy.newProxyInstance(
wrappedValue.getClass().getClassLoader(),
getAllInterfaces(wrappedValue.getClass()),
new D<T_I>(wrappedValue));
}
private static Class[] getAllInterfaces(Class type) {
if (type.isInterface()) {
Class[] all = new Class[type.getInterfaces().length + 1];
int i = 0;
all[i++] = type;
for (Class t : type.getInterfaces()) {
all[i++] = t;
}
return all;
} else {
return type.getInterfaces();
}
}
private final T_I wrappedValue;
private D(T_I wrappedValue) {
this.wrappedValue = wrappedValue;
}
public Object invoke(Object proxy, Method method, Object[] args) {
if (method.getDeclaringClass() == I.class) {
// call wrapped method in D
return method.invoke(this, args);
}
//call unwrapped method of other interface
return methos.invoke(wrappedValue, args);
}
// Methods for I
}
现在您可以通过以下方式使用它:
C1 c1 = ...;
c1 = D.decorate(c1);
关于java - 使用装饰器模式时如何保留接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5999122/