J'ai une classe abstraite Employee avec deux sous-classes concrètes, MinorEmployee et AdultEmployee . Je sais comment créer une méthode de fabrique statique dans Employee qui instancie une instance d'une sous-classe concrète:
public abstract class Employee() {
public static Employee create(LocalTime birthdate) {
if (/* omitted */) {
return new MinorEmployee();
} else {
return new AdultEmployee();
}
}
}
Existe-t-il un moyen en Java d'empêcher un appelant dans le même package de l'instanciation directe d'un MinorEmployee ou AdultEmployee ?
Je ne peux pas rendre leurs constructeurs privés, ou Employee ne pourrait pas y accéder. Je ne veux pas non plus les imbriquer dans Employee.
3 Réponses :
Je peux vous donner une idée de quelque chose que vous pouvez essayer, mais il peut y avoir quelques mises en garde:
créer une classe de fabrique distincte au lieu de la classe de base.
rendre le constructeur privé dans la classe de fabrique
instancie un objet privé factice dans la classe d'usine
Laissez le seul constructeur de MinorEmployee et AdultEmployee accepter l'objet de la classe d'usine. Étant donné que l'objet de fabrique ne peut pas exister en dehors de la classe à cause d'un constructeur privé, pratiquement personne d'autre ne devrait être capable d'instancier ces classes de l'extérieur.
Utilisez l'objet factice à transmettre dans votre méthode de fabrique.
Vous pouvez déclarer les constructeurs dans MinorEmployee et AdultEmployee comme private puis utiliser la réflexion dans votre méthode d'usine:
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
}
}
Une autre façon est:
Vous pouvez rendre les constructeurs privés et utiliser une méthode auxiliaire pour identifier d'où vient la demande de nouvelle entité. Si vient de l'endroit où vous voulez, renvoyez une nouvelle instance de l'objet autrement, vous pouvez lancer et une exception.
Peut-être que si vous avez créé des membres statiques privés
MinorEmployeeetAdultEmployeedeEmployee... Mais si cela a du sens pourEmployeepour accéder à ces constructeurs (en fonction de la portée), alors il devrait être raisonnable de considérer d'autres classes du même package que dans la bonne portée pour le faire aussi ...les classes d'usine devraient idéalement être séparées des classes d'entité, IMO.
Merci, @ernest_k. J'aurais dû indiquer dans la question que je ne veux pas utiliser de classes imbriquées ainsi que des classes internes. J ai mis a jour.