开发者

API design: one generic interface VS three specialized interfaces?

I'm working on a tool where users can use their own annotations to describe data processing workflow (like validation, transformation etc).

Besides using ready-to-use annotations, users can user their own: in order to do this they need to declare annotation class itself, and then implement annotation processor (<--it's the main point of this question actualy).

The configured method for data processing may look like this one:

void foo(@Provide("dataId") @Validate(Validator.class) String str) {    
   doSmth(str); 
}

There're naturally three groups of annotations:

  1. those which produce initial values;
  2. those which transforms values (converters);
  3. those which just read values and perform some work (validators, different consumers).

So I need to make a choise: either create one interface for handling all these types of annotations, which can look like this one:

interface GenericAnnotationProcessor {    
    Object processAnnotation(Annotation annotation, Object processedValue);
}

Or I can add 3 intefaces to the API:

interface ProducerAnnotationProcessor {     
    Object produceInitValue(Annotation annotation);
}

interface TransformerAnnotationProcessor {         
    Object transformValue(Annotation annotation, Object currentValue);
}

interface ConsumerAnnotationProcessor { 
    void consumeValue(Annotation annotation, Object currentValue);
}

The first option is not very clear in use, but the third option pollute开发者_如何学编程s the API with 3 almost similar interfaces.

What would you choose (first of all as an API user) and why?

Thanks!


I would create the first, more general interface, then define the three different implementation classes. Without knowing more about how you will be using this, my first instinct would be to define the Interface and/or a base class (depending upon how much common implementation code was shared between the different processors), and then add specialized processor implementation in derived types, all of whihc share the common interface.

In using the API, I would expect to declare a variable which implements GenericAnnotationProcessor, and then assign the appropriate implementation type depending upon my needs.

It is early here in Portland, OR, but at this moment, at 50% of my required caffeine level, this seems to me like it would provide maximum flexibility while maximizing cade re-use.

Of course, your actual reuirements might dictate otherwise . . .

Hope that was helpful!


Just diving deep into your problem.

As they are executing similar task, with some variance, Strategy pattern #Example should assist you.

Your problem should look like something below.

interface GenericAnnotationProcessor {    
    Object processAnnotation(Annotation annotation, Object processedValue);
}

interface ProducerAnnotationProcessor implements GenericAnnotationProcessor {
}

interface TransformerAnnotationProcessor implements GenericAnnotationProcessor {
}

interface ConsumerAnnotationProcessor implements GenericAnnotationProcessor {
}

Now you can follow example from Wiki

class Context {

    // map of annotation processors

    // register(add/remove) annotation processors to the map

    public int executeAnnotationProcessor(Annotation annotation, Object processedValue) {
        return locateAnnotationProcessor(annotation).processAnnotation(annotation, processedValue);
    }

    private GenericAnnotationProcessor locateAnnotationProcessor(Annotation annotation) {
        // return expected annotation processor
    }
}

I believe you can understand.


You can use Interfaces Extending Interfaces More on there

Similar to classes, you can build up inheritance hierarchies of interfaces by using the extends keyword, as in:

interface Washable {
    void wash();
}

interface Soakable extends Washable {
    void soak();
}

In this example, interface Soakable extends interface Washable. Consequently, Soakable inherits all the members of Washable. A class that implements Soakable must provide bodies for all the methods declared in or inherited by Soakable, wash() and soak(), or be declared abstract. Note that only interfaces can "extend" other interfaces. Classes can't extend interfaces, they can only implement interfaces.

Hope it helps.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜