2

In C++, I understand that it is possible to create a Singleton base class using templates. It is described in the book, Modern C++ Design, by Andrei Alexandrescu.

Can something like this be achieved in Java?

Rollin_s
  • 1,983
  • 2
  • 18
  • 18
  • 1
    Why would you want to do that? The Singleton is basically an anti-pattern, you know? –  May 27 '09 at 15:47
  • 1
    One reason might be that he wants to find out how to instantiate an instance of an unknown class. In other words, given the class as a aprameter do something like this: Object instance = clazz instanceof Singleton ? (Singleton) clazz.getInstance() : new clazz(); (This of course requires a parameterless constructor to be available, but that's a different issue). – n3rd May 27 '09 at 15:50
  • 3
    @Elvian: Like everything, Singleton is good when it is good, and not when it is not. Part of being a good programmer is knowing when and when not to apply patterns and existing solutions should the problem not fit. In other words, it's not Singleton's fault when one doesn't know when to apply it properly. – Welbog May 27 '09 at 15:51
  • 1
    The short answer is probably yes, but I need more detail of exactly what you're looking for. – Pesto May 27 '09 at 15:52
  • @Welbog: I agree sometimes you have a good reason to use very localized singletons (even if it make impossible to Unit test your code without using some Inversion of control mechanisms), but a "generalized singleton" seems like a crazy idea to me. Why not set the whole object and its properties public. Easier, same effect (almost ;)) –  May 27 '09 at 15:57

5 Answers5

3

Because Java's generics are not reified, it isn't possible to implement a generalized Singleton in the same way. Because the generic types are "erased" from the compiled code, the singleton would have to be explicitly initialized at runtime.

The upshot is, a Singleton template would not provide much value in Java.

erickson
  • 265,237
  • 58
  • 395
  • 493
  • Even if generics were reified it still wouldn't work without other modifications to the language. For instance, statics would still be shared by all parameterisations of the same class. – Tom Hawtin - tackline May 27 '09 at 16:09
  • With reified generics, I can envision an implementation that reflects on the actual type to find a class member variable. I might speculate, but I guess I should draw the line at meta-speculation. – erickson May 27 '09 at 16:24
3

I have yet to see a satisfactory solution for this in Java. There are many examples using templates in C++ or generics in .NET, but Java's generics implementation has some limitations with static members that make this difficult.

The best option I've seen is to use a static HashMap, and a factory class. This allows you to make a single factory that can serve multiple Singletons of any class.

For an implementation, see this post.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
2

Yes, but all approaches have their flaws. They are either expensive (using synchronized) or make testing impossible (final static).

See the links to the right:

"State of the art" is to use a container or factory which creates the singletons as needed and keeps them in some kind of cache. See Spring, Guice, etc.

Community
  • 1
  • 1
Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
1

You can use a static HashMap(or Hashtable for thread safety) to store all instances for different templates as @reed-copsey mentioned. Example Singleton class:

public class Singleton<T extends Parent> {
    private static HashMap<Class, Singleton> instanceMap = new HashMap<Class, Singleton>();

    private Singleton() {

    }

    public static <T> Singleton getInstance(Class<T> tClass) {
        if (!instanceMap.containsKey(tClass))
            instanceMap.put(tClass, new Singleton());
        return instanceMap.get(tClass);
    }

}

You can use this singleton as:

public static void main(String[] args) {
    Singleton instance1 = Singleton.getInstance(Child1.class);
    Singleton instance2 = Singleton.getInstance(Child1.class);
    assert instance1 == instance2;

    Singleton instance3 = Singleton.getInstance(Child2.class);
    assert instance1 != instance3;
}

Singleton class will return different instance for different class types.

1

In 1997 I tried to do this with JDK 1.0.2 and came to the conclusion that it was not possible to make an inheritable singleton. As far as I can tell Java has not gained any new features that would allow this.

However, doing this manually does not involve a lot of boilerplate code, maybe 10 lines or so per class. If you need to make some sort of anonymous factory mechanism the singletons could implement an interface with placeholders for the instantiation protocol.

ConcernedOfTunbridgeWells
  • 64,444
  • 15
  • 143
  • 197
  • A good singleton is three lines of code. The class declaration, the instance declaration and initializer, and the private constructor. – erickson May 27 '09 at 16:26