假设我有一个包含许多公共方法的类:
public class MyClass {
public void method1() {}
public void method2() {}
(...)
public void methodN() {}
}
现在我想创建一个wrapper类,它将所有方法委托给包装实例(delegate):
public class WrapperClass extends MyClass {
private final MyClass delegate;
public WrapperClass(MyClass delegate) {
this.delagate = delegate;
}
public void method1() { delegate.method1(); }
public void method2() { delegate.method2(); }
(...)
public void methodN() { delegate.methodN(); }
}
现在,如果 MyClass 有很多方法,我需要重写它们中的每一个,这或多或少与“委托”的代码相同。我想知道是否可以做一些魔法来自动调用 Java 中的方法(因此 Wrapper 类需要说“嘿,如果你调用我的方法,只需转到delegate对象并对其调用此方法)。
顺便说一句:我不能使用继承,因为委托不在我的控制之下。我只是从其他地方获取它的实例(另一种情况是如果 MyClass 是最终的)。
注意:我不想要 IDE 生成。我知道我可以在 IntelliJ/Eclipse 的帮助下做到这一点,但我很好奇这是否可以在代码中完成。
有什么建议如何实现这样的目标吗? (注意:我可能可以使用某些脚本语言(例如 php)来完成此操作,我可以使用 php 魔术函数来拦截调用)。
或许动态Proxy
java 可以帮助你。仅当您因此使用接口时它才有效。在这种情况下,我将调用该接口MyInterface
并设置默认实现:
public class MyClass implements MyInterface {
@Override
public void method1() {
System.out.println("foo1");
}
@Override
public void method2() {
System.out.println("foo2");
}
@Override
public void methodN() {
System.out.println("fooN");
}
public static void main(String[] args) {
MyClass wrapped = new MyClass();
wrapped.method1();
wrapped.method2();
MyInterface wrapper = WrapperClass.wrap(wrapped);
wrapper.method1();
wrapper.method2();
}
}
包装类的实现如下所示:
public class WrapperClass extends MyClass implements MyInterface, InvocationHandler {
private final MyClass delegate;
public WrapperClass(MyClass delegate) {
this.delegate = delegate;
}
public static MyInterface wrap(MyClass wrapped) {
return (MyInterface) Proxy.newProxyInstance(MyClass.class.getClassLoader(), new Class[] { MyInterface.class }, new WrapperClass(wrapped));
}
//you may skip this definition, it is only for demonstration
public void method1() {
System.out.println("bar");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Method m = findMethod(this.getClass(), method);
if (m != null) {
return m.invoke(this, args);
}
m = findMethod(delegate.getClass(), method);
if (m != null) {
return m.invoke(delegate, args);
}
return null;
}
private Method findMethod(Class<?> clazz, Method method) throws Throwable {
try {
return clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
} catch (NoSuchMethodException e) {
return null;
}
}
}
注意这个类:
- extends
MyClass
,继承默认实现(任何其他都可以)
- 实施
Invocationhandler
,允许代理进行反射
- 可选地实施
MyInterface
(满足装饰器模式)
此解决方案允许您重写特殊方法,但委托所有其他方法。这甚至可以与 Wrapper 类的子类一起使用。
注意该方法findMethod
尚未捕获特殊情况。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)