web-dev-qa-db-fra.com

Méthode d'usine statique en classe de base

Une définition de plus en plus populaire de la méthode d'usine est la suivante: une méthode statique d'une classe qui renvoie un objet de type de classe. Mais contrairement à un constructeur, l'objet actuel qu'il retourne pourrait être une instance d'une sous-classe. enter image description here

De: - https://sourcemakaking.com/design_patterns/factory_method

Ne violera-t-il pas OCP?

J'ai également vu cela dans le code de production.

Quelle serait la bonne implémentation?

Je peux penser à une classe de créateurs distincte avec une méthode statique qui renvoie des objets de sous-classe. Ma solution proposée n'est clairement pas une usine abstraite car elle ne crée pas de familles de produits, elle ne correspond à aucun des modèles de créationnels GOF. Donc, je suis sceptique à propos de ma solution.

7
q126y

Selon le Ouvrir/Fermer Principe (OCP) :

Les entités logicielles (classes, modules, fonctions, etc.) doivent être ouvertes à l'extension, mais fermées pour la modification.

Examinons votre architecture statique de l'usine sous cette perspective:

  • Imaginez que nous voulons étendre notre conception horizontalement avec une sous-classe ProductThree. Comment la fonction makeProduct() renvoie un objet qui pourrait être l'une des sous-classes sans connaître le constructeur des sous-classes? Je peux penser à deux approches:
    • Vous devrez peut-être modifier la méthode s'il est implémenté comme un énorme switch ou chaîné if. Cela enfreindrait OCP.
    • Vous pouvez penser à un mécanisme d'auto-inscription qui découle Product à partir de ses sous-classes (par exemple, à l'aide d'une carte/ associative conteneur Mappage d'un nom de classe/identifiant avec une méthode de classe de classe - java exemple ). Cela répondrait à une exigence d'extensibilité et resterait conformes au PCF.
  • Imaginez que nous voulons étendre notre conception verticalement, en spécialisant ProductOne dans ProductOneA et ProductOneB. Pour y parvenir, vous ne pouvez pas compter sur des constructeurs de sous-classe dans makeProduct(). Vous devriez utiliser une fonction makeProductOne(). Cela nécessite que l'auto-inscription soit conçue pour permettre de cascade à travers la hiérarchie. Bien que cela puisse être difficile, cela ne semble pas impossible.
  • Supposons que nous puissions trouver un moyen de mettre en œuvre la nécessité d'auto-enregistrement dans la conception. Dans ce cas, vous pouvez bien sceller la méthode d'usine, conformément à OCP.

En conclusion, le concept de l'usine statique est conforme à OCP. Bien entendu, une implémentation spécifique pourrait enfreindre OCP, mais uniquement s'ils ne tiennent pas compte des exigences supplémentaires que j'ai mentionnées ci-dessus.

Notez que l'utilisation d'une classe d'usine est une approche plus propre: elle applique Séparation des préoccupations (I.E. Évitez que l'usine connaisse les internes du produit). Mais en ce qui concerne l'OCP, l'utilisation d'une méthode statique comme expliquée ci-dessus est une alternative acceptable.

Je ne peux pas dire pour d'autres langues, mais Andrei Alexandrescu a démontré la mise en œuvre d'une méthode d'usine in " Moderne C++ Conception - Programmation générique et modèles de conception appliqués" == @ . Il s'agit d'un OCP complet en utilisant une carte et des fonctions d'enregistrement/désinscription. La seule difficulté qu'il mentionne l'identifiant de type qui doit être fourni à l'usine. Bien sûr, un enum serait un problème d'OCP, mais il a exploré plusieurs alternatives utilisant RTTI ou un générateur d'identification unique pour contourner ce problème.

8
Christophe