views:

85

answers:

2

I am using an enum singletom pattern like this:

public enum LicenseLoader implements ClientLicense {
    INSTANCE;

    /**
     * @return an instance of ClientLicense
     */
    public static ClientLicense getInstance() {
        return (ClientLicense)INSTANCE;
    }

   ...rest of code

}

Now I want to return the Interface and hide the fact that we are actually using an enum at all. I want the client to use getInstance() and not LicenseLoader.INSTANCE as one day I may decide to use a different pattern if necessary.

Is is possible to make INSTANCE private to the enum?

+3  A: 

What about making a public interface and private enum that implements said interface, with a singleton INSTANCE constant?

So, something like this (all in one class for brevity):

public class PrivateEnum {

    public interface Worker {
        void doSomething();
    }

    static private enum Elvis implements Worker {
        INSTANCE;
        @Override public void doSomething() {
            System.out.println("Thank you! Thank you very much!");
        }
    }

    public Worker getWorker() {
        return Elvis.INSTANCE;
    }
}

This way, you're not exposing Elvis.INSTANCE (or even enum Elvis at all), using an interface to define your functionality, hiding all implementation details.

polygenelubricants
Good Idea thanks.
jax
This worked perfectly, it allowed me to make the Worker package private also allowing me to get at some stuff I wanted to keep private to the outside world but available inside the package context.
jax
The `enum` instance is still available, as I explained.
Tom Hawtin - tackline
A: 

All enum constants are accessible. For instance through deserialisation or the enum-specific reflective methods.

As always, I strongly suggest avoiding singletons.

Tom Hawtin - tackline
You are giving bad advice. "The enum singleton pattern provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks." (Effective Java - Joshua Bloch)
jax
No, I'm not giving you bad advice.
Tom Hawtin - tackline
@Tom: what do you mean it's "still available" (comment to my answer)? `private` accessibility modifier on the `enum` is not ironclad (e.g. `setAccessible` attack), but this is true of every `class`, not just `enum`.
polygenelubricants
@polygenelubricants You can read the instance with `ObjectInputStream.readObject`. Also methods such as `Enum.valueOf`.
Tom Hawtin - tackline
@Tom: a naive `Enum.valueOf` wouldn't work since the `private enum` is inaccessible. You can break this, of course, just like you can break anything `private`. I don't think there's anything specific to `enum` that makes it more vulnerable than any other `class` if an attacker is determined. In fact, I think it's harder to attack due to some built-in reflection defense etc.
polygenelubricants
@polygenelubricants Works for me! `public class Priv { private enum En { THING } } class Pub { public static void main(String[] args) throws Exception { Class clazz = Class.forName("Priv$En"); System.err.println(Enum.valueOf(clazz, "THING")); } }`
Tom Hawtin - tackline
@Tom Besides, where are the multiple instances, hence, the singleton pattern! Accessibility is not part of the singleton pattern so your comment, "As always, I strongly suggest avoiding singletons.", is deceiving.
jax
@jax Singletons are evil. From google http://accu.org/index.php/articles/337 http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx
Tom Hawtin - tackline