I’m aiming to create a set of objects, each of which has a unique identifier. If an object already exists with that identifier, I want to use the existing object. Otherwise I want to create a new one. I’m trying not to use the word Singleton, because I know it’s a dirty word here…
I can use a factory method:
// A map of existing nodes, for getInstance. private static Map<String, MyClass> directory = new HashMap<String, MyClass>(); public static MyClass getInstance(String name) { MyClass node = directory.get(name); if(node == null) { node == new MyClass(name); } return node; }
Or equally, I could have a separate MyClassFactory method.
But I had intended to subclass MyClass:
public class MySubClass extends MyClass;
If I do no more, and invoke MySubClass.getInstance():
MyClass subclassObj = MySubClass.getInstance('new name');
… then subclassObj will be a plain MyClass, not a MySubClass.
Yet overriding getInstance() in every subclass seems hacky.
Is there a neat solution I’m missing?
That’s the generalised version of the question. More specifics, since the answerers asked for them.
The program is for generating a directed graph of dependencies between nodes representing pieces of software. Subclasses include Java programs, Web Services, Stored SQL procedures, message-driven triggers, etc.
So each class ‘is-a’ element in this network, and has methods to navigate and modify dependency relationships with other nodes. The difference between the subclasses will be the implementation of the populate() method used to set up the object from the appropriate source.
Let’s say the node named ‘login.java’ learns that it has a dependency on ‘checkpasswd.sqlpl’:
this.addDependency( NodeFactory.getInstance('checkpasswd.sqlpl'));
The issue is that the checkpasswd.sqlpl object may or may not already exist at this time.
The static method is defined on the parent class, and it’s called statically as well. So, there’s no way of knowing in the method that you’ve called it on the subclass. The java compiler probably even resolves the call statically to a call to the parent class.
So you will need to either reimplement the static method in your child classes as you propose, or make them not static so you can inheritance (on a hierarchy of factory objects, not classes), or pass a parameter to signify the type you want to create.
Check out the EnumSet.noneOf() method. It has a similar issue as you do, and it solves it by passing the java.lang.Class method. You could use newInstance on the class. But personally, I’d just use factory objects rather than classes with static methods.