See also: JavaSingleton JavaSingletonProblems SingletonPattern
Now, make some Improvements:
if we make more than one Singleton, we have to write the above Code again and again.
so, use Object Oriented logic, and make a Singleton-Super-Class:
public abstract class Singleton { private Singleton() { } public Singleton(SingletonFactory m) { } }
as you see, Default Constructor is private, so a Subclass must look like this:
public class ExampleSingleton extends Singleton{ public ExampleSingleton(SingletonFactory m) { super(m); } }Do singletons have so much in common that we can justify making them inherit from one base class? Can they be used in a common way? Do they represent the same type? In Java, there is only single inheritance, why to waste it for this? You will never need code like:
if (x instanceof Singleton) ...or
(Singleton) xBesides, the nice feature of singletons is that the code which uses the singleton, does not need to know, the object is a singleton. (Otherwise we cound use static class method instead of singletons) I believe, an abstract base class for Singletons is prime example of PrematureGeneralization. So it not an improvement at all.
If we see a class/type as a group of objects which are similar and behave the same way, then it is just weird to group objects into one class just because each of them is in a group of one. Some sort of class of objects which want to be alone in one's class :-)
-- GregorRayman
So, Use a Singleton Factory:
public final class SingletonFactory { static private SingletonRegistry holder = new SingletonRegistry(); private SingletonFactory() { } /** * Call this like: * <code> * SingletonFactory.getInstance(ExampleSingleton.class); * </code> * @param clazz here: YourSingleton.class * @return Singleton * @throws InstantiationException * @throws InvocationTargetException * @throws IllegalAccessException * @throws NoSuchMethodException if Class is not of Type Singleton!! */ public static Singleton createSingleton(Class clazz) throws InstantiationException, InvocationTargetException, IllegalAccessException, NoSuchMethodException { if (!holder.isRegistered(clazz)) construct(clazz); return holder.lookup(clazz); } /** * Method construct. * * this makes a new Instance of the Singleton. * only called if there is no Instance before. * * * @param clazz * @throws NoSuchMethodException * @throws IllegalAccessException * @throws InvocationTargetException * @throws InstantiationException */ private static void construct(Class clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //get the Constructor // if Class is not of Singleton Type, // this will throw NoSuchMethodException Class[] parameterTypes = {SingletonFactory.class}; Constructor constructor = clazz.getConstructor(parameterTypes); //call the Constructor Object[] initargs = {new SingletonFactory()}; Singleton singleton = (Singleton) constructor.newInstance(initargs); //register it holder.register(singleton); }}
And a Singleton Holder, which works like a Registry:
public class SingletonRegistry {
private Hashtable holder; /** * Constructor for SingletonRegistry. */ public SingletonRegistry() { super(); holder = new Hashtable(); } /** * Method register. * @param singleton */ public void register(Singleton singleton) { holder.put(singleton.getClass().getName(), singleton); } /** * Method lookup. * @param clazz * @return Singleton */ public Singleton lookup(Class clazz) { return (Singleton) holder.get(clazz.getName()); } /** * Method isRegistered. * @param clazz * @return boolean */ public boolean isRegistered(Class clazz) { return (null != holder.get(clazz.getName())); } /** * Method isRegistered. * @param singleton * @return boolean */ public boolean isRegistered(Singleton singleton) { return isRegistered(singleton.getClass()); }}
you cannot Call
ExampleSingleton ex = new ExampleSingleton();because that's not allowed due to the private Constructor.
the only Way to do this is:
Singleton s1 = SingletonFactory.createSingleton(ExampleSingleton.class);
so, every Subclass of Singleton is a own Singleton.
This is just too complicated and makes refactoring more difficult. What if I need to change my class so that it is not a singleton anymore? A solution without one common base class for singletons is much easyier to refactor. Here an example of "refactored" simple singleton:
public class Clock { public static synchronized Clock getInstance() { if (null == theClock) { theClock = new Clock(); } return theClock; } // refactoring: one Clock is not enough anymore, we've got global... public Clock(Timezone timezone) { ... // later we might to refactor this into a factory, with one clock per timezone } private Clock() { ... } private static Clock theClock = null; }To refactor we only added new constructor. No need to change the inheritance hierarchy, no need to change the type of Clock or to touch other classes. Of course, we can add a new public constructor if your system as well, but that would create a class which inherits from class Singleton and is not a singleton. -- GregorRayman
You are Right !! Is there any value in this sort of comment?
KarlKnechtel: I have a pattern of my own for handling Singletons in Java, for the case where you want several related Singleton objects of a common superclass (e.g. for implementing State using Flyweight). See JavaSingletonPackage.
Here's a simple (and fast) singleton
public class Singleton { public final static Singleton Instance = new Singleton(); private Singleton() {} } Singleton theSingleton = Singleton.Instance;