Use a registry
Use a singleton registry to:
Specify singleton classes at runtime
Prevent singleton subclasses from allowing multiple instances
Example 8 lists a singleton class that maintains a registry of singletons, registered by class name:
Example 8. A singleton with a registry
import Java.util.HashMap;
import org.apache.log4j.Logger;
public class Singleton {
private static HashMap map = new HashMap();
private static Logger logger = Logger.getRootLogger();
protected Singleton() {
// Exists only to thwart instantiation
}
public static synchronized Singleton getInstance(String classname) {
if(classname == null) throw new IllegalArgumentException("Illegal classname");
Singleton singleton = (Singleton)map.get(classname);
if(singleton != null) {
logger.info("got singleton from map: " + singleton);
return singleton;
}
if(classname.equals("SingeltonSubclass_One"))
singleton = new SingletonSubclass_One();
else if(classname.equals("SingeltonSubclass_Two"))
singleton = new SingletonSubclass_Two();
map.put(classname, singleton);
logger.info("created singleton: " + singleton);
return singleton;
}
// Assume functionality follows that's attractive to inherit
}
The preceding base class creates subclass instances and stores them in a map. But that base class is high maintenance because you must update its getInstance() method for every subclass. LUCkily, we can use reflection to skirt that issue.
Use reflection
Example 9 lists a singleton with a registry that uses reflection to instantiate a particular class's objects. With this implementation, as opposed to Example 8, the Singleton.getInstance() method does not need to update when new subclasses are implemented.
Example 9. Use reflection to instantiate singletons
import java.util.HashMap;