vendredi 23 octobre 2015

Use one implementation of an interface depending on used generic in implementation

I have two interfaces. One interface contains information, and the second interface is supposed to use the first interface. The second interface have one generic(s) that has to be a implementation of the first interface.

I want to automatically use the implementation of the second interface depending on what implementation of the first interface I receive.

Let me show the interfaces. (I changed domain and simplified it, but you get the basic idea.)

//This contains information needed to publish some information
//elsewhere, on a specific channel (MQ, Facebook, and so on)
public interface PubInfo {

    String getUserName();
    String getPassword();
    String getUrl();

    Map<String, String> getPublishingSettings();
} 



//Implementation of this interface should be for one implementation 
//PubInfo
public interface Publisher<T extends PubInfo> {
    void publish(T pubInfo, String message);
}

Lets assume I would have these implementations of PubInfo...

public class FacebookPubInfo implements PubInfo {
    // ...
}

.

public class TwitterPubInfo implements PubInfo {
    // ...
}

...and these of Publisher

public class FacebookPublisher implements Publisher<FacebookPublisher> {

    @Override
    public void publish(FacebookPublisher pubInfo, String message) {
        // ... do something
    }
}

.

public class TwitterPublisher implements Publisher<TwitterPubInfo> {
    // ...
}    

You get the basic idea, two interfaces with two implementations each.

To the question, finally

Now I'll come to the tricky part for me, and that is that I want to be able to automatically use TwitterPublisher when my service gets a TwitterPubInfo.

I can do that with manual mapping, as you see in the example below, but I can't help to think that it would exist a way to do this more automatically, and not depending upon manual mapping. I use spring, and I think that in there, somewhere it would exist a tool to help me with this, or maybe some other utility class, but I can't find anything.

public class PublishingService {

    private Map<Class, Publisher> publishers = new HashMap<Class, Publisher>();

    public PublishingService() {

        // I want to avoid manual mapping like this
        // This map would probably be injected, but 
        // it would still be manually mapped. Injection
        // would just move the problem of keeping a 
        // map up to date.
        publishers.put(FacebookPubInfo.class, new FacebookPublisher());
        publishers.put(TwitterPubInfo.class, new TwitterPublisher());
    }

    public void publish(PubInfo info, String message) {

        // I want to be able to automatically get the correct
        // implementation of Publisher

        Publisher p = publishers.get(info.getClass());
        p.publish(info, message);

    }

}

I could at least populate publishers in PublishingService with reflections, right?

Do I need to do it myself, or is there any help somewhere else with this?

Or, maybe you think the approach is wrong, and that there exists a smarter way to accomplish what I need to do here, feel free to say that and tell me your superior way :p of doing things (really, I appreciate it).





Aucun commentaire:

Enregistrer un commentaire