代码之家  ›  专栏  ›  技术社区  ›  namin

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

  •  3
  • namin  · 技术社区  · 16 年前

    实现以各种指定方式组合同一接口的某些实例的接口的最佳方法是什么?我需要为多个接口做这项工作,我希望最小化样板文件,并且仍然获得良好的效率,因为我需要这项工作用于关键的生产系统。

    这是问题的简图。

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

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

    现在,假设我想在许多其他接口中实现以下接口:

    Interface Foo {
      String bar(int baz);
    }
    

    我想以这样的代码结束:

    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); } 
        });
      }
    }
    

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

    2 回复  |  直到 16 年前
        1
  •  2
  •   mdma    16 年前

    我会建议使用动态代理——这真的比现在的常规方法调用慢得多吗——我听说反射在加速重复方法调用方面有点神奇。(如果慢了100倍,你确定你会注意到吗?好的,重新阅读你的问题-你会注意到的!)

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

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

    您可能在方面上也取得了一些成功,特别是在编译时或加载时编织方面的AspectJ,因此避免了反射开销。对不起,我不能透露细节。

        2
  •  1
  •   Ha.    16 年前

    您可以反转合并器:

    @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(); 
    }
    

    不是一行而是更容易理解。但是,如果您的方法抛出异常,这将更加复杂。您将需要尝试/捕获块和 addException 方法。