我有一个实现接口的类。还有另一个类实现了这个接口,第二个类的实例支持我的类的实现。
对于接口指定的许多方法,我的类只是将它们直接转发到第二个类。
public class MyClass implements MyInterface
{
private OtherClass otherClassInstance; // Also implements MyInterface.
// ...
void foo() { otherClassInstance.foo(); }
void bar() { otherClassInstance.bar(); }
void baz() { otherClassInstance.baz(); }
// ...
}
简单地从第二个类派生我的类将消除所有这一切,但它没有意义,因为这两个类彼此无关(除了实现一个通用接口)。它们代表了不同的东西 - 我的班级很多实现都复制了其他类的实现。换句话说,我的类是在第二个类的顶层实现的,但它本身不是第二个类的子集。我们知道,继承意味着表达“is-a”关系,而不是分享实现,因此在这种情况下它是不合适的。
约书亚布洛赫演讲的This部分说明了情况。我知道Java对委派没有任何语言支持。但是,至少有一些方法来清理我的类的实现,所以它不是那么多余吗?
答案 0 :(得分:3)
答案并非真正回答您的实际问题:
我会说,住在样板上。让IDE为您生成它。示例:在Netbeans中,添加私有ArrayList字段,将光标设置到您希望方法出现的位置,点击alt-insert,选择“ Generate Delegate Method ... ”,单击方法你想要在对话框中创建一个委托,打开,提交,完成生成的方法并让它们做正确的事,你就完成了。
这有点难看,但是当你只处理一个类时,它仍然更好地开始混淆反射,就像听起来一样。你的课程可能是那种课程,你将完成并完全测试,然后希望永远不再触摸。反射会产生不会消失的运行时成本。在这种情况下,最好在源文件中使用自动生成的样板文件。
答案 1 :(得分:1)
使用http://java.sun.com/javase/6/docs/api/java/lang/reflect/Proxy.html的第一种方法见教程http://docs.oracle.com/javase/1.4.2/docs/guide/reflection/proxy.html
使用AOP的第二种方法是创建调度程序来拦截特定类的所有调用
对于这两种方式,您需要使用反射API管理方法处理
编辑显示想法 以下从上面的教程中获取的代码只是修改了一下(请参阅invoke方法中的youListImpl.getRealArrayList())
public class DebugProxy implements java.lang.reflect.InvocationHandler {
private YouListImpl youListImpl;
public static Object newInstance(Object obj) {
return java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new DebugProxy(obj));
}
private DebugProxy(Object obj) {
this.obj = obj;
}
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable
{
Object result;
try {
System.out.println("before method " + m.getName());
result = m.invoke(youListImpl.getRealArrayList(), args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " +
e.getMessage());
} finally {
System.out.println("after method " + m.getName());
}
return result;
}
}