首页 > 解决方案 > 如何只创建一个父子对象

问题描述

设计一个类,使得只能创建该类的一个实例及其任何子类。澄清一下:假设 A 是这样一个类,而 B 是从 A 派生的。B 除了扩展 A 之外没有任何特殊代码。

class A { 
  // code of class A
}
public class B extends A{
    public static void main(String[] args)
    {
        new A(); // works fine. 
        new A(); // causes an exception 
        new B(); // works fine as this is the first instance of B 
        new B(); // causes an exception.
    }
}

但是我们需要使用new关键字创建对象。

我尝试在父级中定义静态值,但这没有帮助。

标签: java

解决方案


class A {

    private static Map<Class<? extends A>, A> instances = new HashMap<>();

    public A() {
        synchronized (A.class) {
            if (instances.containsKey(this.getClass())) {
                throw new IllegalStateException();
            }
            instances.put(getClass(), this);
        }
    }
    // code of class A
}

public class B extends A {

    public static void main(String[] args) {
        new A(); // works fine. 
        new A(); // causes an exception 
        new B(); // works fine as this is the first instance of B 
        new B(); // causes an exception.
    }
}

当您创建 的实例A或任何子类时,将调用它A的构造函数。A

构造函数检查 的实例A是否存在于Map instances.

如果当前类的实例存在,则抛出异常。

如果当前类的实例不存在(当没有抛出异常时),则当前对象被保存到instances.

在所有实例中使用的Map都是static相同的(如果每个实例都有自己的Map,它显然不会工作)。AMap

该块通过锁定对象来synchronized确保映射访问是线程安全的。锁定当前对象不是线程安全的,因为在创建新对象时方法不是线程安全的。ClassAClassputHashMap

您还可以按照oleg.cherednik的答案中所述锁定instances或使用 a Setof Classes 。


推荐阅读