Java 以编程方式实现以各种指定方式组合同一接口的某些实例的接口

Java 以编程方式实现以各种指定方式组合同一接口的某些实例的接口,java,reflection,code-generation,proxy-classes,Java,Reflection,Code Generation,Proxy Classes,实现以各种指定方式组合同一接口的某些实例的接口的最佳方法是什么?我需要对多个接口执行此操作,我希望尽量减少样板文件,同时仍能实现良好的效率,因为我需要对关键生产系统执行此操作 这是问题的简图 抽象地说,我有一个通用组合器类,它接受实例并指定各种组合器: class Combiner<I> { I[] instances; <T> T combineSomeWay(InstanceMethod<I,T> method) { // ...

实现以各种指定方式组合同一接口的某些实例的接口的最佳方法是什么?我需要对多个接口执行此操作,我希望尽量减少样板文件,同时仍能实现良好的效率,因为我需要对关键生产系统执行此操作

这是问题的简图

抽象地说,我有一个通用组合器类,它接受实例并指定各种组合器:

class Combiner<I> {
   I[] instances;

   <T> T combineSomeWay(InstanceMethod<I,T> method) {
     // ... method.call(instances[i]) ... combined in some way ...
   }

   // more combinators
}
我想以这样的代码结束:

class FooCombiner implements Foo {
  Combiner<Foo> combiner;

  @Override 
  public String bar(final int baz) {
    return combiner.combineSomeWay(new InstanceMethod<Foo, String> {
      @Override public call(Foo instance) { return instance.bar(baz); } 
    });
  }
}
类FooCombiner实现Foo{
合路器;
@凌驾
公共字符串栏(最终整数baz){
返回combiner.combineSomeWay(新实例方法{
@重写公共调用(Foo实例){return instance.bar(baz);}
});
}
}

现在,如果接口有很多方法,这可能会很快变得冗长。我知道我可以使用Java反射API中的动态代理来实现这样的接口,但是通过反射进行方法访问的速度要慢上百倍。那么,在这种情况下,除了样板文件和反射,还有什么替代方法呢?

我会建议使用动态代理——它真的比现在的常规方法调用慢得多吗?我听说反射在幕后发挥了相当大的魔力,加快了重复的方法调用。(如果速度慢100倍,你确定你会注意到吗?好的,重读你的问题-你会注意到的!)

否则,您的问题基本上有了解决方案:使用命令对象将每个方法包装到接口中。然后,可以将接口集合中的每个实例传递给命令对象进行处理

当然,如果您感到勇敢和冒险,您可以使用cglib、javassist或orther生成命令对象的实现,以及使用动态类生成生成组合器接口的实现。这样可以避免使用样板文件


您可能在方面也取得了一些成功,特别是在编译时或加载时编织方面,aspectJ,因此您可以避免反射开销。抱歉,我无法提供详细信息。

您可以反转您的合路器:

@Override
public String bar(int baz)
{
    //for (Foo f:combiner.combineSomeWay())// returns Iterator<Foo>
    for (Foo f:combiner) //combiner must implement Iterable<Foo> or Iterator<Foo>
    {
        // In case of several ways to combine
        // add() method should call some temp object
        // in combiner created (or installed) by 
        // combineSomeWay.
        // The best temp object to use is Iterator
        // returned by combiner.combineSomeWay();
        combiner.add(f.bar(baz));// or addResult, or addCallResult
    }
    // clear (or uninstall) temp object and result
    // thats why get* method 
    // name here is bad.
    return combiner.done(); 
}
@覆盖
公共字符串栏(int baz)
{
//for(Foo f:combiner.combineSomeWay())//返回迭代器
for(Foo f:combiner)//组合器必须实现Iterable或迭代器
{
//如果有几种方式可以组合
//add()方法应该调用一些临时对象
//在由创建(或安装)的组合器中
//组合方式。
//最好使用的临时对象是迭代器
//由combiner.combineSomeWay()返回;
combiner.add(f.bar(baz));//或addResult,或addCallResult
}
//清除(或卸载)临时对象和结果
//这就是get*方法的原因
//这里的名字不好。
返回组合器.done();
}

不是一行一行,但更容易理解。但是,如果您的方法抛出异常,那么这将更加复杂。您需要try/catch块和
addException
方法。

这是一个相当大的标题!这是个不错的主意,但在我的情况下它不起作用,因为我希望组合器决定是否调用该方法(例如,一个组合器只调用第一个实例的方法,而忽略其他方法)。不管怎样,谢谢你,这就是为什么我在这里使用迭代器而不是集合。当需要调用方法时,组合器必须通过迭代器提供对象,并且它可以根据add方法的参数决定迭代器将返回的下一个元素。延续将大大简化组合器,但java还不支持它们。啊,这很聪明。。。在任何情况下,在每个方法中都有一个for循环仍然是非常简单的。但这是一个很好的技巧。我最终使用了动态代理,而且更干净了。此外,速度的减慢并不明显,因为方法访问速度无论如何都很快。
@Override
public String bar(int baz)
{
    //for (Foo f:combiner.combineSomeWay())// returns Iterator<Foo>
    for (Foo f:combiner) //combiner must implement Iterable<Foo> or Iterator<Foo>
    {
        // In case of several ways to combine
        // add() method should call some temp object
        // in combiner created (or installed) by 
        // combineSomeWay.
        // The best temp object to use is Iterator
        // returned by combiner.combineSomeWay();
        combiner.add(f.bar(baz));// or addResult, or addCallResult
    }
    // clear (or uninstall) temp object and result
    // thats why get* method 
    // name here is bad.
    return combiner.done(); 
}