web-dev-qa-db-fra.com

Quelle est la différence entre le motif de conception de générateur et le motif de conception d'usine?

Quelle est la différence entre le modèle de conception Builder et le modèle de conception Usine? 

Lequel est le plus avantageux et pourquoi? 

Comment représenter mes résultats sous forme de graphique si je souhaite tester et comparer/contraster ces modèles?

525
Penguen

Avec les modèles de conception, il n’ya généralement pas de solution "plus avantageuse" qui fonctionne dans tous les cas. Cela dépend de ce que vous devez implémenter.

De Wikipedia: 

  • Le constructeur se concentre sur la construction d'un objet complexe, étape par étape. Abstrait L'usine met l'accent sur une famille de produits objets (simples ou complexes) . Builder renvoie le produit en tant que version finale étape, mais aussi loin que le résumé L'usine est concernée, le produit obtient est retourné immédiatement.
  • Builder construit souvent un composite.
  • Souvent, les conceptions commencent par utiliser la méthode Factory (moins compliquée, plus Personnalisable, les sous-classes prolifèrent). et évoluez vers Abstract Factory, Prototype ou constructeur (plus flexible, Plus complexe) en tant que concepteur découvre où plus de flexibilité est nécessaire.
  • Parfois, les modèles de création sont complémentaires: Builder peut en utiliser un des autres modèles à mettre en œuvre quels composants sont construits. Abstrait L'usine, le constructeur et le prototype peuvent utiliser Singleton dans leur mises en œuvre.

Entrée Wikipedia pour modèle de conception d'usine: http://fr.wikipedia.org/wiki/Factory_method_pattern

Entrée Wikipedia pour le modèle de conception de générateur: http://en.wikipedia.org/wiki/Builder_pattern

384
Adrian Grigore

Une fabrique est simplement une fonction d'emballage autour d'un constructeur (éventuellement d'une classe différente). La principale différence est qu'un modèle de méthode factory nécessite que l'objet entier soit construit en un seul appel de méthode, tous les paramètres étant transmis sur une seule ligne. L'objet final sera retourné.

Un modèle de constructeur, en revanche, est essentiellement un objet wrapper qui regroupe tous les paramètres possibles que vous pourriez vouloir transmettre à un appel de constructeur. Cela vous permet d'utiliser des méthodes de définition pour construire lentement votre liste de paramètres. Une méthode supplémentaire sur une classe de générateur est une méthode build (), qui passe simplement l'objet de générateur au constructeur souhaité et renvoie le résultat.

Dans les langages statiques tels que Java, cela devient d'autant plus important que vous avez plus d'une poignée de paramètres (potentiellement optionnels), car cela évite d'avoir à utiliser des constructeurs télescopiques pour toutes les combinaisons possibles de paramètres. De plus, un générateur vous permet d’utiliser des méthodes de définition pour définir des champs en lecture seule ou privés qui ne peuvent pas être modifiés directement après l’appel du constructeur.

Exemple d'usine de base

// Factory
static class FruitFactory {
    static Fruit create(name, color, firmness) {
        // Additional logic
        return new Fruit(name, color, firmness);
    }
}

// Usage
Fruit fruit = FruitFactory.create("Apple", "red", "crunchy");

Exemple de générateur de base

// Builder
class FruitBuilder {
    String name, color, firmness;
    FruitBuilder setName(name)         { this.name     = name;     return this; }
    FruitBuilder setColor(color)       { this.color    = color;    return this; }
    FruitBuilder setFirmness(firmness) { this.firmness = firmness; return this; }
    Fruit build() {
        return new Fruit(this); // Pass in the builder
    }
}

// Usage
Fruit fruit = new FruitBuilder()
        .setName("Apple")
        .setColor("red")
        .setFirmness("crunchy")
        .build();

Il peut être intéressant de comparer les exemples de code de ces deux pages wikipedia:

http://en.wikipedia.org/wiki/Factory_method_pattern
http://fr.wikipedia.org/wiki/Builder_pattern

261
James McGuigan

Le modèle Usine peut presque être considéré comme une version simplifiée du modèle Builder.

Dans le modèle Factory, l’usine est chargée de créer différents sous-types d’un objet en fonction des besoins.

L'utilisateur d'une méthode factory n'a pas besoin de connaître le sous-type exact de cet objet. Un exemple de méthode d'usine createCar peut renvoyer un objet Ford ou Honda.

Dans le modèle Builder, différents sous-types sont également créés par une méthode de générateur, mais la composition des objets peut différer au sein de la même sous-classe.

Pour continuer l'exemple de voiture, vous pouvez utiliser une méthode de générateur createCar qui crée un objet Honda- avec un moteur 4 cylindres ou un objet Honda- avec 6 cylindres. Le modèle de construction permet cette granularité plus fine.

Les diagrammes du modèle de générateur et du modèle de méthode Factory sont disponibles sur Wikipedia.

255
Ben S

Le modèle de conception de générateur décrit un objet qui sait comment créer un autre objet d'un type spécifique en plusieurs étapes. Il contient l'état requis pour l'élément cible à chaque étape intermédiaire. Pensez à ce que StringBuilder traverse pour produire une chaîne finale.

Le modèle de conception d'usine décrit un objet qui sait créer plusieurs types d'objets différents mais liés en une étape, le type spécifique étant choisi en fonction de paramètres donnés. Pensez au système de sérialisation, où vous créez votre sérialiseur et il construit l’appel souhaité dans un appel de chargement tout en un.

53
Joel Coehoorn
  • Construire un objet complexe pas à pas: modèle de générateur

  • Un objet simple est créé en utilisant une seule méthode: pattern de méthode factory

  • Création d'un objet à l'aide de la méthode de fabrique multiple: modèle de fabrique abstraite

40

Les deux sont des modèles de création, pour créer un objet.

1) Modèle d'usine - Supposons que vous avez une super classe et un nombre N de sous-classes . L'objet créé dépend du paramètre/de la valeur transmis.

2) Modèle de générateur - pour créer un objet complexe.

Ex: Make a Loan Object. Loan could be house loan, car loan ,
    education loan ..etc. Each loan will have different interest rate, amount ,  
    duration ...etc. Finally a complex object created through step by step process.
13
Tony

Tout d'abord quelques choses générales pour suivre mon argumentation:

Le principal défi de la conception de grands systèmes logiciels est qu’ils doivent être flexibles et faciles à modifier. Pour cette raison, il existe certains paramètres comme le couplage et la cohésion. Pour obtenir des systèmes dont les fonctionnalités peuvent facilement être modifiées ou étendues sans avoir à repenser entièrement le système, vous pouvez suivre les principes de conception (comme SOLID, etc.). Après un certain temps, certains développeurs ont reconnu que s’ils suivaient ces principes, des solutions similaires s’appliqueraient bien à des problèmes similaires. Ces solutions standard se sont avérées être les modèles de conception.

Les modèles de conception doivent donc vous aider à suivre les principes de conception généraux afin de réaliser des systèmes à couplage lâche avec une grande cohésion.

Répondant à la question:

En demandant la différence entre deux modèles, vous devez vous demander quel modèle rend votre système plus flexible. Chaque modèle a son propre objectif d'organiser les dépendances entre les classes de votre système.

Modèle de fabrique abstraite: GoF: “Fournit une interface pour la création de familles d’objets apparentés ou dépendants sans spécifier leurs classes concrètes.”

Qu'est-ce que cela signifie: En fournissant une interface comme celle-ci, l'appel au constructeur de chacun des produits de la famille est encapsulé dans la classe d'usine. Et comme il s'agit du seul endroit de votre système où ces constructeurs sont appelés, vous pouvez modifier votre système en implémentant une nouvelle classe d'usine. Si vous échangez la représentation de l’usine par le biais d’une autre, vous pouvez échanger tout un ensemble de produits sans toucher à la majorité de votre code.

Le modèle de construction: GoF: “Séparez la construction d'un objet complexe de sa représentation afin que le même processus de construction puisse créer différentes représentations.”

Qu'est-ce que cela signifie: Vous encapsulez le processus de construction dans une autre classe, appelée le directeur (GoF). Ce directeur contient l’algorithme de création de nouvelles instances du produit (par exemple, composez un produit complexe à partir d’autres parties). Pour créer les parties intégrantes de l'ensemble du produit, le directeur utilise un constructeur. En échangeant le générateur dans le directeur, vous pouvez utiliser le même algorithme pour créer le produit, mais modifier les représentations des pièces individuelles (et donc la représentation du produit). Pour étendre ou modifier votre système dans la représentation du produit, il vous suffit d'implémenter une nouvelle classe de générateur.

En bref: L’objet de Abstract Factory Pattern est d’échanger un ensemble de produits conçus pour être utilisés ensemble. L’objet du modèle de construction est d’encapsuler l’algorithme abstrait de création d’un produit afin de le réutiliser pour différentes représentations du produit.

À mon avis, vous ne pouvez pas dire que le motif abstrait est le grand frère du motif bâtisseur. OUI, ce sont deux modèles de création, mais l’intention principale des modèles est tout à fait différente.

10
Janis

Builder Pattern et Factory Pattern, les deux ressemblent beaucoup aux yeux nus car ils créent tous deux des objets pour vous.

Mais vous devez regarder de plus près

Cet exemple concret fera la différence entre les deux plus clairement. 

Supposons que vous alliez dans un fast-food et que vous commandiez Food

1) Quelle nourriture?

Pizza 

2) Quelles garnitures?

Capsicum, Tomate, Poulet BBQ, NO ANANAS 

Ainsi, différents types d’aliments sont fabriqués selon le modèle d’usine, mais les différentes variantes (saveurs) d’un aliment particulier sont créées selon le modèle Builder. 

Différents types d'aliments

Pizza, Burger, Pâtes 

Variantes de Pizza

Seulement Fromage, Fromage + Tomate + Capsicum, Fromage + Tomate etc. 

Échantillon de code

Vous pouvez voir l'exemple d'implémentation de code des deux modèles ici
Modèle de construction
Modèle d'usine

7
Rohit Singh

Une différence frappante entre constructeur et usine que je pouvais distinguer était la suivante

supposons que nous ayons une voiture

class Car
{
  bool HasGPS;
  bool IsCityCar;
  bool IsSportsCar;
  int   Cylenders;
  int Seats;

  public:
     void Car(bool hasGPs=false,bool IsCityCar=false,bool IsSportsCar=false, int Cylender=2, int Seats=4);
 };

Dans l'interface ci-dessus, nous pouvons obtenir une voiture de la manière suivante:

 int main()
 {
    BadCar = new Car(false,false,true,4,4);
  }

mais que se passe-t-il si une exception se produit lors de la création des sièges ??? VOUS N'AVERA PAS L'OBJET AT ALL //BUT

supposons que vous ayez une implémentation comme celle-ci 

class Car
 {
    bool mHasGPS;
    bool mIsCityCar;
    bool mIsSportsCar;
    int mCylenders;
    int mSeats;

 public:
    void Car() : mHasGPs(false), mIsCityCar(false), mIsSportsCar(false), mCylender(2), mSeats(4) {}
    void SetGPS(bool hasGPs=false)  {mHasGPs = hasGPs;}
    void SetCity(bool CityCar)  {mIsCityCar = CityCar;}
    void SetSports(bool SportsCar)  {mIsSportsCar = SportsCar;}
    void SetCylender(int Cylender)  {mCylenders = Cylender;}    
    void SetSeats(int seat) {mSeats = seat;}    
};

 class CarBuilder 
 {
    Car* mCar;
public:
        CarBuilder():mCar(NULL) {   mCar* = new Car();  }
        ~CarBuilder()   {   if(mCar)    {   delete mCar;    }
        Car* GetCar()   {   return mCar; mCar=new Car();    }
        CarBuilder* SetSeats(int n) {   mCar->SetSeats(n); return this; }
        CarBuilder* SetCylender(int n)  {   mCar->SetCylender(n); return this;  }
        CarBuilder* SetSports(bool val) {   mCar->SetSports(val); return this;  }
        CarBuilder* SetCity(bool val)   {   mCar->SetCity(val); return this;    }
        CarBuilder* SetGPS(bool val)    {   mCar->SetGPS(val); return this; }
}

Maintenant, vous pouvez créer comme ça 

 int main()
 {
   CarBuilder* bp =new CarBuilder;
    Car* NewCar  = bp->SetSeats(4)->SetSports(4)->SetCity(ture)->SetGPS(false)->SetSports(true)->GetCar();

     bp->SetSeats(2);

     bp->SetSports(4);

     bp->SetCity(ture);

     bp->SetSports(true)

     Car* Car_II=  bp->GetCar();

  }

Ici, dans le deuxième cas, même si une opération échoue, vous obtiendrez toujours la voiture.

Peut-être que la voiture ne fonctionnera pas parfaitement plus tard, mais vous auriez l'objet.

Parce que la méthode d'usine vous donne la voiture en un seul appel, alors que le constructeur construit un par un.

Bien que, cela dépend des besoins du daigne lequel aller pour.

6
Fooo

Builder et Abstract Factory ont des objectifs différents. En fonction du cas d'utilisation approprié, vous devez sélectionner un modèle de conception approprié. 

Builder caractéristiques principales:

  1. Le modèle de générateur construit un objet complexe à l'aide d'objets simples et d'une approche pas à pas.
  2. Une classe Builder construit l’objet final étape par étape. Ce constructeur est indépendant des autres objets
  3. Remplacement de la méthode Factory/Abstract Factory dans ce scénario: Trop nombreux arguments à transmettre du programme client à la classe Factory pouvant être sujets à des erreurs
  4. Certains paramètres peuvent être facultatifs, contrairement à Factory qui oblige à envoyer tous les paramètres

Factory (Simple Factory) caractéristiques principales:

  1. Motif de création
  2. Basé sur l'héritage
  3. Factory renvoie une méthode Factory (interface) qui à son tour renvoie un objet concret.
  4. Vous pouvez substituer de nouveaux objets concrets à l'interface et le client (appelant) ne doit pas être au courant de toutes les implémentations concrètes.
  5. Le client n'a toujours accès qu'à l'interface et vous pouvez masquer les détails de création d'objet dans la méthode Factory.

Souvent, les conceptions utilisent la méthode Factory (moins compliquées, plus personnalisables, les sous-classes prolifèrent) et évoluent vers Abstract Factory, Prototype ou Builder (plus flexible, plus complexe). ) 

Jetez un coup d'œil aux articles liés:

Garder le constructeur dans une classe séparée (interface fluide)

Modèles de conception: Méthode vs usine vs usine abstraite

Vous pouvez vous référer aux articles ci-dessous pour plus de détails:

fabrication de la source

journaldev

4
Ravindra babu
+-------------------------------------------------------------------+---------------------------------------------------+
|                              Builder                              |                      Factory                      |
+-------------------------------------------------------------------+---------------------------------------------------+
| Return only single instance to handle complex object construction | Retrun various instances on multiple constructors |
| No interface required                                             | Interface driven                                  |
| Inner classes is involved (to avoid telescopic constructors)      | Subclasses are involved                           |
+-------------------------------------------------------------------+---------------------------------------------------+  

Modèle de constructeur télescopique

Analogie: 

  • Factory: Considérons un restaurant. La création du "repas du jour" est un motif d'usine, car vous dites à la cuisine "procure-moi le repas du jour" et la cuisine (l'usine) décide quel objet générer, en fonction de critères cachés.
  • Constructeur: Le générateur apparaît si vous commandez une pizza personnalisée. Dans ce cas, le serveur dit au chef d'établissement "J'ai besoin d'une pizza; ajoutez-y du fromage, des oignons et du bacon!" Ainsi, le générateur expose les attributs que doit avoir l'objet généré, mais cache comment les définir.

Courtesy

4
Premraj

Les motifs Abstract Factory et Builder sont tous deux des modèles de création, mais d’intention différente.

Abstract Factory Pattern met l'accent sur la création d'objet pour des familles d'objets liés où:

  • Chaque famille est un ensemble de classes dérivées d’une classe/interface de base commune.
  • Chaque objet est renvoyé immédiatement à la suite d'un appel.

Modèle de construction se concentre sur la construction pas à pas d'un objet complexe. Il sépare la représentation du processus de construction de l'objet complexe, de sorte que le même processus de construction puisse être utilisé pour différentes représentations.

  • L'objet Builder encapsule la configuration de l'objet complexe.
  • L'objet Director connaît le protocole d'utilisation du générateur, où le protocole Définit toutes les étapes logiques nécessaires à la création de l'objet complexe. 
3
Saurabh Kumar

Une construction complexe se produit lorsque l'objet à construire est composé de différents autres objets représentés par des abstractions.

Considérez un menu dans McDonald's. Un menu contient une boisson, un plat principal et un côté. Selon les descendants des abstractions individuelles qui sont composées ensemble, le menu créé a une autre représentation.

  1. Exemple: Cola, Big Mac, Frites
  2. Exemple: Sprite, Nuggets, Frites Frisées

Là, nous avons deux instances du menu avec des représentations différentes. Le processus de construction reste à son tour le même. Vous créez un menu avec un verre, un plat principal et un côté.

En utilisant le modèle de générateur, vous séparez l'algorithme de création d'un objet complexe des différents composants utilisés pour le créer.

En termes de modèle de construction, l'algorithme est encapsulé dans le directeur alors que les constructeurs sont utilisés pour créer les parties intégrales. Faire varier le constructeur utilisé dans l'algorithme du directeur donne une représentation différente car les autres parties sont composées dans un menu. La manière dont un menu est créé reste la même.

2
Janis

Les deux sont très similaires, mais si vous avez un grand nombre de paramètres pour la création d'objets avec certains d'entre eux facultatifs avec des valeurs par défaut, optez pour le modèle Builder.

1
Praveen Kumar

La principale différence entre eux est que le modèle Builder principalement décrit la création pas à pas d'objets complexes. Dans le motif Abstract Factory, l’accent est mis sur familles d’objets-produits. Le générateur renvoie le produit dans le dernière étape. Dans le motif Abstract Factory, le produit est disponible immédiatement.

Exemple: disons que nous créons Maze

1. Abstract Factory:

Maze* MazeGame::CreateMaze (MazeFactory& factory) {
Maze* maze = factory.MakeMaze(); /// product is available at start!!
 /* Call some methods on maze */
return maze;
}

2. Constructeur:

Maze* MazeGame::CreateMaze (MazeBuilder& builder) {
builder.buildMaze(); /// We don't have access to maze
 /* Call some methods on builder */
return builder.GetMaze();
}
1
XYZ123

Je crois que l’utilisation et la différence entre les modèles Factory & Builder peuvent être comprises/clarifiées plus facilement au cours d’une certaine période de temps, car vous avez travaillé sur la même base de code et les mêmes exigences. 

D'après mon expérience, vous commencez généralement par un modèle Factory comprenant deux méthodes de création statique. Au fur et à mesure que la hiérarchie de vos objets devient plus complexe (ou que vous ajoutez de nouveaux types), vous finirez probablement par avoir plus de paramètres dans vos méthodes et par le fait que vous devrez recompiler votre module Factory. Tous ces éléments augmentent la complexité de vos méthodes de création, diminuent la lisibilité et fragilisent le module de création.

Ce point sera peut-être le point de transition. Transition du modèle d'usine au constructeur. Ce faisant, vous créez un module wrapper autour des paramètres construction et vous pourrez ensuite représenter de nouveaux objets (similaires) en ajoutant des abstractions supplémentaires (peut-être) et des implémentations sans toucher à la logique de création. Vous avez donc eu une logique moins complexe et un code source recompilé

Franchement, parler de quelque chose comme «avoir un objet créé en une ou plusieurs étapes est la différence», car le seul facteur de diversité ne me suffisait pas pour les distinguer, car je pouvais utiliser les deux méthodes dans presque tous les cas que je rencontrais maintenant sans éprouver aucun avantage. C'est donc ce que j'ai finalement pensé à cela.

1
stdout

La différence est claire Dans le modèle de générateur, le générateur crée un type d'objet spécifique à votre place. Vous devez dire quel constructeur doit construire . Dans le modèle d'usine, à l'aide de la classe abstraite, vous construisez directement l'objet spécifique.

Ici, la classe de constructeur sert de médiateur entre la classe principale et les classes de type spécifiques . Plus d'abstraction.

1
user2738678

Factory : Utilisé pour créer une instance d'un objet où les dépendances de l'objet sont entièrement détenues par la fabrique. Pour le modèlefabrique abstraite, il existe souvent de nombreuses implémentations concrètes de la même fabrique abstraite. La bonne implémentation de l'usine est injectée via une injection de dépendance.

Builder : Utilisé pour construireimmutableobjects, lorsque les dépendances de l'objet à instancier sont en partie connues à l'avance et en partie fournies par le client du constructeur.

0
Hamady C.

Le motif de construction met l'accent sur la complexité de la création d'objet (résolu par des "étapes")

Le motif abstrait met "juste" l'accent sur "l'abstraction" d'objets (multiples mais liés).

0
Sandeep Jindal

Constructeur et usine abstraite

Le modèle de conception du générateur est très similaire, dans une certaine mesure, au modèle de l'usine abstraite. C'est pourquoi il est important de pouvoir faire la différence entre les situations d'utilisation de l'une ou de l'autre. Dans le cas de Abstract Factory, le client utilise les méthodes de cette dernière pour créer ses propres objets. Dans le cas du générateur, la classe du générateur est expliquée sur la manière de créer l'objet, puis il lui est demandé de le créer, mais la façon dont la classe est assemblée dépend de la classe du générateur, ce détail faisant la différence entre les deux modèles.

Interface commune pour les produits

En pratique, les produits créés par les constructeurs de béton ont une structure très différente, donc s’il n’ya pas de raison de déduire des produits différents d’une classe parente commune. Cela distingue également le motif Builder du motif Abstract Factory qui crée des objets dérivés d'un type commun.

De: http://www.oodesign.com/builder-pattern.html

0
Arturas M

Les deux modèles ont la même nécessité: masquer à un code client la logique de construction d'un objet complexe. Mais qu'est-ce qui fait qu'un objet "complexe" (ou parfois complique)? C'est principalement dû à des dépendances, ou plutôt à l'état d'un objet composé d'états plus partiels. Vous pouvez injecter des dépendances par constructeur pour définir l'état initial de l'objet, mais un objet peut en nécessiter beaucoup, certaines seront dans un état initial par défaut (le fait même de savoir que définir une dépendance par défaut sur NULL n'est pas le moyen le plus propre ) et un autre ensemble à un état entraîné par une condition. De plus, il y a des propriétés d'objet qui sont une sorte de "dépendances inconscientes" mais elles peuvent aussi assumer des états optionnels.

il existe deux manières bien connues de dominer cette complexité:

  • Composition/agrégation: Construisez un objet, construisez ses objets dépendants, puis connectez-les ensemble. Ici, un constructeur peut rendre transparent et flexible le processus qui détermine les règles qui régissent la construction du composant.

  • Polymorphisme: les règles de construction sont déclarées directement dans la définition du sous-type. Vous avez donc un ensemble de règles pour chaque sous-type et une condition détermine quelle règle parmi celles-ci s'applique à la construction de l'objet. Une usine s'inscrit parfaitement dans ce scénario.

Rien n'empêche de mélanger ces deux approches. Une famille de produits pourrait créer un objet abstrait avec un générateur, un constructeur pourrait utiliser des fabriques pour déterminer quel objet composant instancierait.

0
Carmine Ingaldi

A mon humble avis

Builder est une sorte d’usine plus complexe.

Mais dans Builder, vous pouvez instancier des objets avec l’utilisation d’autres fabriques , nécessaires pour créer un objet final et valide.

Ainsi, en parlant de l'évolution des "motifs créatifs" par complexité, vous pouvez le penser de la manière suivante:

Dependency Injection Container -> Service Locator -> Builder -> Factory
0
v.babak

À mon avis, le motif de générateur est utilisé lorsque vous souhaitez créer un objet à partir d'un groupe d'autres objets et que la création d'une pièce doit être indépendante de l'objet que vous souhaitez créer. Il est utile de masquer la création d'une partie du client pour rendre le générateur et le client indépendants. Il est utilisé pour la création d'objets complexes (objets pouvant contenir des propriétés complexes)

While pattern spécifie que vous voulez créer des objets d'une famille commune et que vous voulez qu'il soit immédiatement généré. Il est utilisé pour des objets plus simples. 

0
AjayLohani