Idea is to create a factory class that returns different singleton instances based on a 'type'. [Multiton pattern]. Also, the singleton instances should be lazily created.
Is the below code thread safe? Using ConcurrentHashMap makes it simpler but I want to try with HashMap.
public class Multiton {
private HashMap<String, Interface> interfaceMap;
private static class Holder {
public static final Multiton INSTANCE = new Multiton();
}
public static Multiton getInstance() {
return Holder.INSTANCE;
}
private Multiton(){
interfaceMap = new HashMap<String, Interface>();
}
public Interface getInterface(String key){
Interface value = interfaceMap.get(key);
if(null == value){
synchronized(interfaceMap){
// double check locking
if(interfaceMap.get(key) == null){
switch(key){
case TypeA : // initialize Type A interface here and put it to map
value = new TypeA();
interfaceMap.put(key, value);
break;
case TypeB : // initialize Type B interface here and put it to map
value = new TypeB();
interfaceMap.put(key, value);
break;
}
}
}
}
return interfaceMap.get(key);
}
}
Double checked locking is (in general) not thread safe. In particular, it is not sufficient to only synchronize when writing to a map, as that does not prevent a reader thread from accessing the state a writer thread is currently modifying.
If you can't use a ConcurrentHashMap (for instance because you must ensure that a single TypeA is created, not just that a single TypeA is used by all clients), the following should work and be reasonably cheap. In particular, it is lock free once the lazy object has been constructed.
For production quality, you might want to consider using lamdba expressions for the factory methods, and type safe keys for the map (such as the class objects of the interface requested).