213 votes

Constructeurs et méthodes d'usine

Lors de la modélisation de classes, quelle est la manière préférée d'initialiser :

  1. Constructeurs, ou
  2. Méthodes d'usine

Et quelles seraient les considérations à prendre en compte pour utiliser l'un ou l'autre ?

Dans certaines situations, je préfère avoir une méthode de fabrique qui renvoie null si l'objet ne peut pas être construit. Cela rend le code plus ordonné. Je peux simplement vérifier si la valeur renvoyée n'est pas nulle avant de prendre une autre mesure, contrairement à la levée d'une exception depuis le constructeur. (Personnellement, je n'aime pas les exceptions)

Disons que j'ai un constructeur sur une classe qui attend une valeur d'identification. Le constructeur utilise cette valeur pour remplir la classe à partir de la base de données. Dans le cas où un enregistrement avec l'id spécifié n'existe pas, le constructeur lève une exception RecordNotFoundException. Dans ce cas, je devrai inclure la construction de toutes ces classes dans un bloc try..catch.

En revanche, je peux avoir une méthode d'usine statique sur ces classes qui retournera null si l'enregistrement n'est pas trouvé.

Quelle approche est la meilleure dans ce cas, le constructeur ou la méthode d'usine ?

256voto

David Pokluda Points 4284

Demandez-vous ce qu'ils sont et pourquoi nous les avons. Ils sont tous deux là pour créer l'instance d'un objet.

ElementarySchool school = new ElementarySchool();
ElementarySchool school = SchoolFactory.Construct(); // new ElementarySchool() inside

Aucune différence jusqu'à présent. Imaginons maintenant que nous ayons plusieurs types d'école et que nous voulions passer de l'école élémentaire à l'école secondaire (qui est dérivée d'une école élémentaire ou qui implémente la même interface ISchool que l'école élémentaire). Le changement de code serait le suivant :

HighSchool school = new HighSchool();
HighSchool school = SchoolFactory.Construct(); // new HighSchool() inside

Dans le cas d'une interface, nous aurions :

ISchool school = new HighSchool();
ISchool school = SchoolFactory.Construct(); // new HighSchool() inside

Maintenant, si vous avez ce code à plusieurs endroits, vous pouvez voir que l'utilisation de la méthode factory peut être assez bon marché car une fois que vous changez la méthode factory, vous avez terminé (si nous utilisons le deuxième exemple avec les interfaces).

Et c'est là la principale différence et le principal avantage. Lorsque vous commencez à traiter des hiérarchies de classes complexes et que vous voulez créer dynamiquement une instance d'une classe à partir d'une telle hiérarchie, vous obtenez le code suivant. Les méthodes d'usine peuvent alors prendre un paramètre qui indique à la méthode quelle instance concrète elle doit instancier. Disons que vous avez une classe MyStudent et que vous devez instancier l'objet ISchool correspondant pour que votre étudiant soit membre de cette école.

ISchool school = SchoolFactory.ConstructForStudent(myStudent);

Vous avez maintenant un seul endroit dans votre application qui contient la logique métier qui détermine quel objet ISchool doit être instancié pour différents objets IStudent.

Ainsi, pour les classes simples (objets de valeur, etc.), le constructeur est parfait (vous ne voulez pas suringénier votre application), mais pour les hiérarchies de classes complexes, la méthode d'usine est préférable.

De cette façon, vous suivez le premier principe de conception de la livre gang of four "Programmer pour une interface, pas pour une implémentation".

4 votes

Même si vous pensez que c'est une classe simple, il y a une chance que quelqu'un ait besoin d'étendre votre classe simple, donc la méthode factory est toujours meilleure. Par exemple, vous pouvez commencer avec ElementarySchool mais plus tard quelqu'un (y compris vous-même) peut l'étendre avec PrivateElementarySchool et PublicElementarySchool.

18 votes

Ceci devrait être la réponse acceptée

3 votes

David, bonne réponse, mais pouvez-vous développer un exemple où chaque mise en œuvre d'interface peut exiger des paramètres différents pour la construction. Voici un exemple stupide : IFood sandwich = new Sandwich(Cheese chz, Meat meat); y IFood soup = new Soup(Broth broth, Vegetable veg); Comment l'usine ou le constructeur peuvent-ils aider ?

81voto

cherouvim Points 18550

Vous devez lire (si vous avez accès à) Java 2 efficace Point 1 : envisager des méthodes d'usine statiques au lieu des constructeurs. .

Avantages des méthodes d'usine statique :

  1. Ils ont des noms.
  2. Ils ne sont pas tenus de créer un nouvel objet à chaque fois qu'ils sont invoqués.
  3. Ils peuvent retourner un objet de n'importe quel sous-type de leur type de retour.
  4. Ils réduisent la verbosité de la création d'instances de type paramétrées.

Inconvénients des méthodes d'usine statiques :

  1. Lorsque vous ne fournissez que des méthodes d'usine statiques, les classes sans constructeur public ou protégé ne peuvent pas être sous-classées.
  2. Elles ne se distinguent pas facilement des autres méthodes statiques.

6 votes

Il me semble qu'il s'agit plutôt d'un grave bogue de Java que d'un problème général d'OOD. Il existe de nombreux langages OO qui n'ont même pas besoin de ont constructeurs, mais la sous-classe fonctionne parfaitement.

1 votes

@cherouvim pourquoi la plupart du code est écrit en utilisant des Constructors si ( factory methods are better than Constructors. ( Item-1 ) ) Effective java

0 votes

De bons points. Mais c'est spécifique à Java. On peut plaider en faveur d'une caractéristique du langage qui permette de distinguer les méthodes d'usine des autres méthodes statiques.

65voto

Glenn Points 3787

Extrait de la page 108 de Design Patterns : Elements of Reusable Object-Oriented Software par Gamma, Helm, Johnson, et Vlissides.

Utilisez le modèle Factory Method lorsque

  • une classe ne peut pas anticiper la classe des objets qu'elle doit créer
  • une classe veut que ses sous-classes spécifient les objets qu'elle crée
  • délègue la responsabilité à une sous-classe d'aide parmi plusieurs, et vous souhaitez localiser la connaissance de la sous-classe d'aide qui est le délégué.

27 votes

La méthode d'usine statique est différente du modèle de conception GoF - Factory Method Pattern. stackoverflow.com/questions/929021/

0 votes

Veuillez ne pas comparer avec le modèle Factory method des modèles de conception GoF.

179 votes

Cela ne m'explique rien

40voto

Frederick The Fool Points 9092

Par défaut, les constructeurs doivent être préférés, car ils sont plus simples à comprendre et à écrire. Cependant, si vous avez spécifiquement besoin de découpler les subtilités de la construction d'un objet de sa signification sémantique telle qu'elle est comprise par le code client, il est préférable d'utiliser des fabriques.

La différence entre les constructeurs et les fabriques est analogue à celle qui existe entre une variable et un pointeur vers une variable. Il y a un autre niveau d'indirection, ce qui est un inconvénient, mais il y a aussi un autre niveau de flexibilité, ce qui est un avantage. Ainsi, lorsque vous faites un choix, vous seriez bien avisé de faire cette analyse coût/bénéfice.

18 votes

Ainsi, (style TDD) vous commencerez par les constructeurs comme le moyen le plus simple de faire le travail. Et puis vous remaniez vers les fabriques lorsque vous commencez à avoir des odeurs de code (comme une logique conditionnelle répétée déterminant quel constructeur appeler) ?

2 votes

Un point très important. Une étude sur les utilisateurs comparant les fabriques et les constructeurs a donné des résultats très significatifs indiquant que les fabriques nuisent à la convivialité des API : "les utilisateurs ont besoin de beaucoup plus de temps (p=0,005) pour construire un objet avec une fabrique qu'avec un constructeur". [[Le modèle d'usine dans la conception d'API : Une évaluation de l'utilisabilité](https://www.cs.cmu.edu/~NatProg/papers/Ellis2007FactoryUsability.pdf) ].

10voto

Eugen Labun Points 451

Une citation de "Effective Java", 2e édition, Point 1 : Considérez les méthodes de fabrique statiques au lieu des constructeurs, p. 5 :

"Notez que une méthode d'usine statique n'est pas la même chose que le modèle Factory Method de Design Patterns [Gamma95, p. 107]. La méthode de fabrique statique décrite dans cet article n'a pas d'équivalent direct dans les Design Patterns".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X