如果要装饰的对象实现了其他接口的不同组合,那么如何在不丢失额外接口方法的情况下实现装饰器?例如,假设我们有以下类和接口,其中我是我们关心的装饰,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的实例,我们就无法访问I1,I2,I3和I4的其他方法,这些方法可以实现。
答案 0 :(得分:1)
如果C1,C2,C3为接口,则会有代理解决方案。
interface C1 extends I, I1, I2
否则你需要一个像cglib这样的库来装饰这个类。
代理与通用工厂方法相结合将保留其他接口,因此您无需在代码中进行强制转换:
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);
答案 1 :(得分:0)
接口就是这样的。
interface I
{
I objI {get;} // can hold reference to other objects of type I or null
// If the requirement is to make setter as public, that should be fine as well.
// You can have decorator related behavior here
void DecoratorBehavior1();
void DecoratorBehavior2();
}
D类不需要执行换行。它的作用是实现我。
class D implements I
{
public I objI {get; private set;}
// You can have other overloaded constructors as well
D(I obj)
{
this.objI = obj;
}
}
类型I的对象包含对类型I的其他对象的引用或null。该对象可以实现其他类型的接口,也可以从其他基类派生。
如果要使用其他类型的方法,可以将对象类型转换为相应的类型并使用。在进行类型转换之前,您可以验证对象是否确实属于某种类型。
....
I objC1 = new C1(null);
I objC2 = new C2(objC1);
I objC3 = new C3(objC2);
I objD = new D(objC3);
...
I oGetBackC3 = objD.objI;
if(oGetBackC3 is typeof(C3))
{
C3 oGotBackC3 = (C3)oGetBackC3;
...
// You can now call C3 methods on object
}
....
我已经在C#中编写了代码片段,但对于Java来说它也可能保持相同。
答案 2 :(得分:0)
您可以使用Proxy.newProxy()作为装饰器。你给它一个要实现的接口列表,你可以编程包含和处理任意数量的接口,如果你愿意,可以添加一些接口。你唯一不能做的就是让Proxy扩展给定的类。