简体   繁体   中英

How to protect instantiation of concrete subclasses when using factory pattern?

I have an abstract class Employee with two concrete subclasses, MinorEmployee and AdultEmployee . I know how to create a static factory method in Employee that instantiates an instance of a concrete subclass:

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

Is there a way in Java to prevent a caller in the same package from directly instantiating a MinorEmployee or AdultEmployee ?

I can't make their constructors private, or Employee wouldn't be able to access them. I also don't want to nest them inside of Employee .

I can give you hint on something you can try, though there can be some caveats:

  • create a separate factory class instead of base class.

  • make the constructor private in the the factory class

  • instantiate a dummy private object in the factory class

  • Let MinorEmployee and AdultEmployee 's only constructor accept object of factory class. Since object of factory can not exist out side the class due to private constructor, practically no one else should be able to instantiate those classes from outside.

  • Use the dummy object to pass on in your factory method.

You could declare the constructors in MinorEmployee and AdultEmployee as private and then use reflection in your factory method:

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
    }
}    

Another way is:

You can make the constructors private and use an auxiliary method to identify from where the request of new entity is coming. If is coming from where you want, return a new instance of the object else, you can throw and an exception.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM