Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Polymorphic factory / getInstance() in Java

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.

like image 370
slim Avatar asked Nov 25 '08 16:11

slim


People also ask

What is the use of getInstance () in Java?

The getInstance() is the method of Java Currency class which is used to get an instance of currency for the given currency code.

What is Factory Method in Java example?

It is a creational design pattern that talks about the creation of an object. The factory design pattern says that define an interface ( A java interface or an abstract class) for creating object and let the subclasses decide which class to instantiate.

Which pattern do you see in the code below Java Util calendar getInstance ()?

java. util. Calendar, ResourceBundle and NumberFormat getInstance() methods uses Factory pattern.

Why is getInstance static?

for a singleton pattern, getInstance IS a static method, and uses static attrs. The whole point of static is to have things associated with the class instead of a specific object. The singleton pattern guarantees that you will have one instance of an object of that type.


3 Answers

Have you looked into Guice? Not sure if it would solve your problem exactly, but it acts as a generic factory and dependency injection container, and eliminates non-type safe String keys.

like image 77
bajafresh4life Avatar answered Oct 19 '22 07:10

bajafresh4life


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.

like image 40
Wouter Lievens Avatar answered Oct 19 '22 08:10

Wouter Lievens


after reading you explanation of the problem i think your making it very difficult for yourself by sub classing in your graph construction. i think the problem becomes much more simple if you separate the dependency graph from the "program information"

use an Interface such as:

Public Interface Node<T> {
  public Object<T>    getObject();
  public String       getKey();
  public List<String> getDependencies();
  public void         addDependence(String dep);
}

and then use a factory to instantiate you nodes

like image 28
pvgoddijn Avatar answered Oct 19 '22 07:10

pvgoddijn