仅允许父工厂方法实例化子类
我毫不怀疑这已被问到并在这里回答了十几次,但我找不到满意的答案。
我有一个类的系列,我只想通过像这样的静态方法实例化抽象父类(我可能在这里打字错误,我在打字而不试图编译)。
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
来限制它,并且只能在单个静态工厂调用的上下文中进行限制。
但说实话,我不会打扰!
几种可能的替代方案:
-
使用子类构造函数的默认可见性,并将它们放在与父类相同的包中。 这样做的缺点是这些类可以由同一个包中的任何其他类实例化,包括任何“兄弟”类。
-
将所有子类作为父类中的嵌套类。 将它们标记为
private static
将使它们仅对父类可见。 不幸的是,这也意味着在同一个文件中拥有所有类的代码……