Java Design Patterns – Joshua Bloch Enum Singleton and Third-Party APIs

design-patternsjavaobject-oriented-designpatterns-and-practicessingleton

In the book Effective Java he give the best Singleton pattern implementation in his, that is implement by a Enum. I have doubt to how to implement this pattern with a third party API.

I'm using an third party API that provides an interface IRCApi that has a lot of methods like:

public interface IRCApi{
    void connect();
    void disconnect();          
    void disconnect(String aQuitMessage);
    void joinChannel(String aChannelName); 
    //...
}

My question: Is the code snippet below a valid implementation of that design pattern with all benefits cited by Joshua Bloch (multi thread support, facility to change, etc):

public enum IRCApiSingleton {
    INSTANCE;

    private final IRCApi ircApi = new IRCApiImpl(false);

    public final IRCApi get() {
        return ircApi;
    }
}

using this way:
IRCApiSingleton.get().connect();

Or do I have to make my enum implement IRCApi and encapsulate all methods of an IRCApi implementation (there are about 40 methods), like:

public enum IRCApiSingleton implements IRCApi {
    INSTANCE {
        private IRCApi impl = new IRCApiImpl(true);    
        @Override
        public void connect() {
            impl.connect();

        }

        @Override
        public void disconnect() {
            impl.disconnect();
        }
        //...
    };
}

and use the INSTANCE directly?

Best Answer

Well, as I see it, IRCApiImpl has a public constructor making it difficult to call either way a "classical singleton".

Still, I'd say that if you follow the guideline of not creating another instance of IRCApiImpl at any other point or even better, making the class inaccessable, you can use either implementation.

From a strict Software-Engineering point of view, the first implementation would be preferable, because It would allow less coupling and would not need to be changed when the API of IRCApiImpl changed.

Personally though I'd prefer the second implementation, which saves you the .get() on every call.

Related Topic