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

时间:2012-06-18 12:22:36

标签: java inheritance

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

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

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()创建?

2 个答案:

答案 0 :(得分:3)

如果你绝对,肯定地想要强制执行此操作,那么给Papa一个受保护的构造函数,该构造函数接受Xyzzy类型的参数。在Xyzzy中将Papa设为受保护的内部类。给它一个私有的构造函数。现在,只有Papa才能生成Xyzzy的实例。由于您需要Xyzzy的实例来调用Papa的构造函数,并且由于Papa的子类必须从其构造函数调用其构造函数,因此您需要Xyzzy的实例调用Papa的任何子类的构造函数。因此,只有Papa可以调用其子类的构造函数。即使Xyzzy没有做任何事情。

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

但说实话,我不会打扰!

答案 1 :(得分:3)

有几种可能的选择:

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

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