仅允许父工厂方法实例化子类

我毫不怀疑这已被问到并在这里回答了十几次,但我找不到满意的答案。

我有一个类的系列,我只想通过像这样的静态方法实例化抽象父类(我可能在这里打字错误,我在打字而不试图编译)。

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 */ } } 

这或多或少是我现在所拥有的。 我想做的是确保Child只能通过工厂方法Papa.newInstance()实例化。 我试图通过将Child的无参数构造函数设为私有来做到这一点,但是后来Papa无法实例化它。

所以,我的问题是,如何确保子实例仅由工厂方法Papa.newInstance()创建?

如果你绝对,积极地想要强制执行这个,那么给Papa一个受保护的构造函数,它接受一个Xyzzy类型的参数。 让Xyzzy成为Papa受保护的内部类。 给它一个私有的构造函数。 现在,只有Papa可以制作Xyzzy实例。 因为你需要一个Xyzzy实例来调用Papa的构造函数,并且由于Papa子类必须从它们的构造函数中调用它的构造函数,你需要一个Xyzzy实例来调用Papa的任何子类的构造函数。 因此,只有Papa可以调用其子类的构造函数。 尽管Xyzzy没有做任何事情。

子类可能泄漏他们的Xyzzy实例,这将允许其他代码调用子类构造函数。 但是你也可以通过单独使用Xyzzy来限制它,并且只能在单个静态工厂调用的上下文中进行限制。

但说实话,我不会打扰!

几种可能的替代方案:

  1. 使用子类构造函数的默认可见性,并将它们放在与父类相同的包中。 这样做的缺点是这些类可以由同一个包中的任何其他类实例化,包括任何“兄弟”类。

  2. 将所有子类作为父类中的嵌套类。 将它们标记为private static将使它们仅对父类可见。 不幸的是,这也意味着在同一个文件中拥有所有类的代码……