Java:只允许一个类进行实例化

时间:2011-08-20 05:05:13

标签: java constructor

我希望合并项目中的某些课程。所以我不希望能够使用:new SomeClass()来实例化这些类,而是使用SomeClass.allocate()从池中获取新项。 我为每个需要汇总的类都有这种代码。

public class GameObject
{
    // Pooling: Provides a static method for allocation and a method for freeing
    private static Pool<GameObject> pool = new Pool<GameObject>();
    public static GameObject allocate() { return pool.obtain(); }
    public void free() { pool.free(this); }
    ...
}

现在我可以通过将默认构造函数设置为私有来禁用实例化的常规方法,但问题是池在创建时需要实例化类,以及池需要扩展时。

是否有某种方法可以将构造仅限于游泳池?

3 个答案:

答案 0 :(得分:2)

我可以看到两个选项:要么使它成为池的内部类,要么使allocate方法包为private,并将其放在与池相同的包中。

编辑:啊。只需将构造函数设为私有,然后覆盖Pool用于创建新实例的任何方法。作为使用上面框架的(粗略)示例:

public abstract class Pool<T>
{
    public abstract T getNewObject();

    public T obtain(){ return getNewObject(); }

    public void free(T obj) {}
}

public class GameObject
{
    // Pooling: Provides a static method for allocation and a method for freeing
    private static Pool<GameObject> pool = new Pool<GameObject>(){
          public GameObject getNewObject(){ return new GameObject(); }
    };
    public static GameObject allocate() { return pool.obtain(); }
    private GameObject(){}
    public void free() { pool.free(this); }
}

GameObject的构造函数很高兴其他人无法访问。

答案 1 :(得分:2)

作为最后的手段,您可以使用反射。对于其他选择,其他人已经说过。 我记得Spring容器能够使用私有构造函数的init类。我很惊讶。我想它也使用这个技巧。好处可能是它更通用。

public static void main(String... args) {
    try {
      Constructor c = GameObject.class.getDeclaredConstructor();
      c.setAccessible(true); // solution
      c.newInstance();

      // production code should handle these exceptions more gracefully
    } catch (InvocationTargetException x) {
      x.printStackTrace();
    } catch (NoSuchMethodException x) {
      x.printStackTrace();
    } catch (InstantiationException x) {
      x.printStackTrace();
    } catch (IllegalAccessException x) {
      x.printStackTrace();
    }
  }

答案 2 :(得分:1)

Alterative:不要试图让你的代码跳过篮球。使用静态分析来强制执行此类规则。如果你不小心做了一些你不想做的事情,工具会抓住它。