使用工厂模式时如何保护具体子类的实例化?

时间:2019-03-04 06:56:57

标签: java factory-pattern

我有一个抽象类Employee,其中有两个具体的子类MinorEmployeeAdultEmployee。我知道如何在Employee中创建静态工厂方法来实例化具体子类的实例:

public abstract class Employee() {
    public static Employee create(LocalTime birthdate) {
        if (/* omitted */) {
            return new MinorEmployee();
        } else {
            return new AdultEmployee();
        }
    }
}

在Java中,有没有一种方法可以防止同一包中的调用者直接实例化MinorEmployeeAdultEmployee

我不能将其构造函数设为私有,否则Employee将无法访问它们。我也不想将它们嵌套在Employee中。

3 个答案:

答案 0 :(得分:2)

尽管有一些警告,但我可以提示您可以尝试的方法

  • 创建一个单独的工厂类,而不是基类。

  • 在工厂类中使构造函数私有化

  • 实例化工厂类中的虚拟私有对象

  • MinorEmployeeAdultEmployee的唯一构造函数接受工厂类的对象。由于工厂的对象由于私有构造函数而不能存在于类之外,因此几乎没有人可以从外部实例化那些类。

  • 使用伪对象以工厂方法进行传递。

答案 1 :(得分:0)

您可以在MinorEmployeeAdultEmployee中将构造函数声明为private,然后在工厂方法中使用反射:

public static Employee create(LocalTime birthdate) {
    try {
        Class<? extends Employee> clazz;
        if (omitted) {
            clazz = MinorEmployee.class;
        } else {
            clazz = AdultEmployee.class;
        }
        Constructor<? extends Employee> cons = clazz.getConstructor();
        cons.setAccessible(true);
        return cons.newInstance();
    } catch (NoSuchMethodException | SecurityException
            | InstantiationException | IllegalAccessException
            | InvocationTargetException ex) {
        // handle the exception
    }
}    

答案 2 :(得分:0)

另一种方法是:

您可以将构造函数设为私有,并使用辅助方法来标识新实体请求的来源。如果来自您想要的位置,则返回该对象的新实例,否则可以引发和异常。

how to figure out what class called a method in java?