Programmatically implementing an interface that co

2019-05-11 04:19发布

What is the best way to implement an interface that combines some instances of the same interface in various specified ways? I need to do this for multiple interfaces and I want to minimize the boilerplate and still achieve good efficiency, because I need this for a critical production system.

Here is a sketch of the problem.

Abstractly, I have a generic combiner class which takes the instances and specify the various combinators:

class Combiner<I> {
   I[] instances;

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

   // more combinators
}

Now, let's say I want to implement the following interface among many others:

Interface Foo {
  String bar(int baz);
}

I want to end up with code like this:

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

Now, this can quickly get long and winded if the interfaces have lots of methods. I know I could use a dynamic proxy from the Java reflection API to implement such interfaces, but method access via reflection is hundred times slower. So what are the alternatives to boilerplate and reflection in this case?

2条回答
该账号已被封号
2楼-- · 2019-05-11 04:54

You can reverse your combiners:

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

Not a one-liner but easier to understand. That would be more complex if your methods throw exceptions though. You will need try/catch block and addException method.

查看更多
神经病院院长
3楼-- · 2019-05-11 05:03

I would have suggested dynamic proxies - is it really so much slower than a regular method call these days - I've heard that reflection does quite a bit of magic under the covers to speed repeated method calls. (And if it is 100x slower, are you sure you will you notice? Ok, just re-read your question - you'll notice!)

Otherwise, you basically have the solution in your question: Use a Command object to wrap each method in your interface. You can then pass each instance in the collection of interfaces to the command object for processing.

Of course, if you're feeling brave and adventurous, you could generate the implementation of your command objects, and the implementation of the combiner interface using dynamic class generation, with cglib, javassist, orther dynamic bytecode generator. That would avoid the boilerplate.

You may also have some success with aspects, particularly aspectJ with compile-time or load-time weaving, so you avoid reflection overhead. Sorry I can't give details.

查看更多
登录 后发表回答