John Fitzpatrick
John Fitzpatrick

Reputation: 4349

Only Allow Parent Factory Method to Instantiate Child Classes

I have no doubt this has been asked and answered here a dozen times, but I just can't find a satisfactory answer.

I have a family of classes that I only want instantiated by the abstract parent class through a static method like this (I probably have typos here I am typing without trying to compile).

public abstract class Papa {
    public static Papa newInstance() {
        String strClass = Papa.figureOutTheNameOfChildClassToInstantiate();
        Papa papa = (Papa) Class.forName(strClass).newInstance();
        return papa;
    }
    public abstract void doSomething();
    ...
}
public class Child extends Papa {
    public void doSomething() { /* Do something */ }
}

That's more or less what I have now. What I wish to do is be sure that the Child can only be instantiated by the factory method Papa.newInstance(). I tried to do this by making the Child's no-argument constructor private, but then Papa can't instantiate it.

So, my question is, how can I make sure Child instances are only created by the factory method Papa.newInstance()?

Upvotes: 2

Views: 1935

Answers (2)

thkala
thkala

Reputation: 86403

A couple of possible alternatives:

  1. Use the default visibility for the child class constructors and put them in the same package as the parent class. This has the disadvantage that those classes can be instantiated by any other class in the same package, including any "sibling" classes.

  2. Have all child classes as nested classes in the parent class. Marking them as private static would make them visible only to the parent class. Unfortunately, this also implies having the code of all classes in the same file...

Upvotes: 3

Tom Anderson
Tom Anderson

Reputation: 47233

If you absolutely, positively, want to enforce this, then give Papa a protected constructor which takes a parameter of type Xyzzy. Make Xyzzy a protected inner class in Papa. Give it a private constructor. Now, only Papa can make instances of Xyzzy. Since you need an instance of Xyzzy to call Papa's constructor, and since subclasses of Papa must call its constructor from their constructors, you need an instance of Xyzzy to call the constructor of any subclass of Papa. Hence, only Papa can call the constructors of its subclasses. Even though Xyzzy doesn't do anything.

Subclasses could leak their Xyzzy instance, which would allow other code to call subclass constructors. But you can constrain that too, by making Xyzzy single-use, and only so within the context of a single static factory invocation.

But to be honest, i wouldn't bother!

Upvotes: 4

Related Questions