Quelle est la différence entre le modèle Builder Design et le modèle Factory Design?


663

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

Laquelle est la plus avantageuse et pourquoi?

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


13
Puisqu'ils font des choses différentes, qu'entendez-vous par «avantageux»?
S.Lott

5
Builder est une version plus complexe du constructeur - tandis que la méthode d'usine est simplifiée.
Dávid Horváth

@ DávidHorváth Je ne décrirais pas un constructeur comme "plus complexe". Lorsque vous traitez avec un constructeur qui a 100 paramètres, et que vous ne vous souciez que de 3 d'entre eux, et que vous savez que le nombre de paramètres pourrait changer à l'avenir, l'utilisation du modèle Builder rendrait la vie de chacun beaucoup plus simple.
Aberrant

@Aberrant L'utilisation compliquée et la complexité architecturale sont deux choses différentes. Je me suis concentré sur ce dernier.
Dávid Horváth

Réponses:


466

Avec les modèles de conception, il n'y a généralement pas de solution "plus avantageuse" qui fonctionne pour tous les cas. Cela dépend de ce que vous devez mettre en œuvre.

De Wikipédia:

  • Builder se concentre sur la construction d'un objet complexe étape par étape. Abstract Factory met l'accent sur une famille d'objets produits (simples ou complexes). Le constructeur retourne le produit comme étape finale, mais en ce qui concerne l'usine abstraite, le produit est retourné immédiatement.
  • Le constructeur 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 évoluent vers Abstract Factory, Prototype ou Builder (plus flexible, plus complexe) à mesure que le concepteur découvre où plus de flexibilité est nécessaire.
  • Parfois, les modèles de création sont complémentaires: Builder peut utiliser l'un des autres modèles pour implémenter les composants à construire. Abstract Factory, Builder et Prototype peuvent utiliser Singleton dans leurs implémentations.

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

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


159
C'est exactement la différence. Le Builder n'est nécessaire que lorsqu'un objet ne peut pas être produit en une seule étape. Un bon exemple de cela serait dans le processus de désérialisation d'un objet complexe. Souvent, les paramètres de l'objet complexe doivent être récupérés un par un.
Bernard Igiri

1
Pour la première phrase, je dirais qu'il existe souvent une solution plus avantageuse qui s'applique largement ... nous ne les voyons tout simplement pas, car ils finissent par être cuits directement dans les langages de programmation.
Joel Coehoorn

4
@Joel: Je conviens que certains modèles sont plus courants que d'autres (par exemple, Factory semble être plus courant que Builder), mais ce que je voulais dire, c'est qu'aucun d'entre eux n'est toujours meilleur que l'autre, quel que soit le scénario. .
Adrian Grigore

@AdrianGrigore que se passe-t-il si les deux sont mélangés ?? aso.net mvc a ControllerBuilder qui a défini et obtenu la méthode pour la classe ControllerFactory
AminM

Bonne réponse, bien que 2 choses qui méritent d'être ajoutées sont: 1) Builder est principalement utilisé pour créer des POJO à l'aide de l'API Fluent (par exemple Person.builder (). WithName ("Sam"). WithAge (38) .build (). 2) Dans mon expérience, le générateur est utile pour la création de POJO pour les objets de domaine, tandis que la fabrique est utile pour créer des objets de service comme la classe PdfGeneratorFactory. L'objet de service peut être mis en cache dans l'usine pour plus d'une utilisation, tandis que le générateur crée toujours un nouvel objet par conception.
saurabh.in

359

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

Un modèle de générateur , d'autre part, est essentiellement un objet wrapper autour de tous les paramètres possibles que vous pourriez souhaiter passer dans une invocation 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 générateur dans le constructeur souhaité et renvoie le résultat.

Dans les langages statiques comme Java, cela devient plus important lorsque vous avez plus d'une poignée de paramètres (potentiellement facultatifs), car cela évite d'avoir à avoir des constructeurs télescopiques pour toutes les combinaisons possibles de paramètres. Un générateur vous permet également 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 de base d'usine

// 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 utile de comparer les exemples de code de ces deux pages wikipedia:

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


1
Ce n'est pas l'utilisation correcte du modèle de générateur imo, même dans le lien wiki que vous avez utilisé, l'utilisation est différente. Ce FruitBuilder est un mélange de composants Director et Builder où vous invoquez build () qui devrait appartenir à Director et les setters qui appartiennent au composant Builder. Director doit contenir une logique métier sur la façon de créer un objet à l'aide des méthodes Builders. Les API fluides ne sont pas des modèles de générateur et StringBuilder n'est pas non plus un modèle de générateur.
Kmaczek

282

Le modèle Factory 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 d'usine n'a pas besoin de connaître le sous-type exact de cet objet. Un exemple de méthode d'usine createCarpeut renvoyer un Fordou un Hondaobjet typé.

Dans le Builder modèle, les sous - types différents sont également créés par une méthode de constructeur, mais la composition des objets peuvent différer dans le même sous - classe.

Pour continuer l'exemple de voiture, vous pouvez avoir une createCarméthode de création qui crée un Hondaobjet de type avec un moteur à 4 cylindres ou un Hondaobjet de type avec 6 cylindres. Le modèle de générateur permet cette granularité plus fine.

Des diagrammes du modèle Builder et du modèle de méthode Factory sont disponibles sur Wikipedia.


13
Le motif du générateur est comme un zoom avant sur la construction du grand objet. Le grand objet est composé d'un autre objet qui se compose plus loin comme la récursivité. Alors que l'usine vous fournira la chose en un seul appel. Cette compréhension est-elle correcte?
Fooo

63

Le modèle de conception de générateur décrit un objet qui sait 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 passe 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 seule étape, où le type spécifique est 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'objet souhaité dans un seul appel de chargement.


7
Juste un petit indice: un bon exemple pour le modèle de générateur est "interface fluide" et ADO.NET est plein d'implémentations "usine" et "usine abstraite" (c'est-à-dire DbFactory).
boj

50
  • Construire un objet complexe étape par étape: modèle de générateur

  • Un objet simple est créé en utilisant une seule méthode: modèle de méthode d'usine

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


21

Builder Pattern et Factory pattern, les deux semblent assez similaires aux yeux nus car ils créent tous les deux des objets pour vous.

Mais vous devez regarder de plus près

Cet exemple concret rendra la différence entre les deux plus claire.

Supposons que vous alliez dans un restaurant-minute et que vous commandiez de la nourriture .

1) Quelle nourriture?

Pizza

2) Quelles garnitures?

Capsicum, tomate, poulet BBQ, PAS D' ANANAS

Ainsi, différents types d'aliments sont fabriqués par le modèle Factory, mais les différentes variantes (saveurs) d'un aliment particulier sont fabriquées par le modèle Builder.

Différents types d'aliments

Pizza, Burger, Pâtes

Variantes de pizza

Uniquement fromage, fromage + tomate + poivron, fromage + tomate, etc.

Exemple de code

Vous pouvez voir l'exemple d'implémentation de code des deux modèles ici
Builder Pattern
Factory Pattern


1
Merci d'avoir fourni l'exemple de code! Vos exemples différencient très bien ces 2 modèles.
Rommel Paras

18

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

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

2) Modèle Builder - 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.

12

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

Le principal défi dans la conception de gros systèmes logiciels est qu'ils doivent être flexibles et simples à changer. Pour cette raison, il existe certaines métriques comme le couplage et la cohésion. Pour obtenir des systèmes qui peuvent être facilement modifiés ou étendus dans ses fonctionnalités sans avoir à repenser l'ensemble du système à partir de zéro, 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, il existe des solutions similaires qui fonctionnaient 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 généraux de conception afin de réaliser des systèmes à couplage lâche avec une cohésion élevée.

Répondre à 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.

The Abstract Factory Pattern: GoF: "Fournir une interface pour créer des familles d'objets lié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 parce que c'est le 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 une autre, vous pouvez échanger un ensemble complet de produits sans toucher à la majorité de votre code.

The Builder Pattern: GoF: "Séparez la construction d'un objet complexe de sa représentation afin que le même processus de construction puisse créer des représentations différentes."

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, composer un produit complexe à partir d'autres parties). Pour créer les parties intégrales de l'ensemble du produit, le directeur utilise un constructeur. En échangeant le constructeur dans le directeur, vous pouvez utiliser le même algorithme pour créer le produit, mais modifier les représentations des pièces uniques (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 constructeur.

Donc, en bref: le but de Abstract Factory Pattern est d'échanger un ensemble de produits qui sont faits pour être utilisés ensemble. Le but du Builder Pattern est d'encapsuler l'algorithme abstrait de création d'un produit pour le réutiliser pour différentes représentations du produit.

À mon avis, vous ne pouvez pas dire que le modèle abstrait d'usine est le grand frère du modèle de constructeur. OUI, ce sont deux modèles de création, mais l'intention principale des modèles est entièrement différente.


belle réponse, expliquez en détail.
2017

pouvez-vous expliquer la signification de "Séparer la construction d'un objet complexe de sa représentation"
Rajdeep

@Rajdeep l'explication est trop longue pour un commentaire, c'est pourquoi j'ai écrit une autre réponse.
Janis

@Janis Où est cette réponse ou cette source d'où je peux lire?
Rajdeep

@Rajdeep je vous recommande de lire le livre "Design Patterns" - amazon.de/Patterns-Elements-Reusable-Object-Oriented-Software/…
Janis

7

Une différence frappante entre Builder et Factory 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 la voiture de la manière suivante:

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

mais si, une exception se produit lors de la création des sièges ??? VOUS N'OBTIENDREZ PAS DU TOUT L'OBJET // MAIS

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

Vous pouvez maintenant 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 fonctionne pas parfaitement plus tard, mais vous auriez l'objet.

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

Bien que cela dépende des besoins du digne pour lequel aller.


2
Il est certainement préférable de ne pas avoir de voiture du tout qu'une voiture invalide - et si vous ne rencontrez le problème que lorsque vous venez utiliser les pauses?
Ken

@Ken: Je n'insiste pas sur le fait que c'est une bonne conception de la perspective d'un projet commercial, etc., plutôt l'intention de citer cet exemple pour illustrer la différence entre les modèles. Définitivement, vous avez raison de dire que c'est mauvais d'après l'expérience des utilisateurs qui obtient une mauvaise voiture, mais, considérez, il y a une usine dans laquelle les voitures sont fabriquées et une partie fonctionne mal, puis la voiture est produite mais avec une mauvaise pause qui serait découverte à le temps de test et d'expédition de cette voiture au client est arrêté.
Fooo

2
Je tiens à préciser que je suis en fait un grand fan du modèle de constructeur, cependant, pas pour la raison que vous avez donnée. Un objet invalide devrait échouer lors de la construction, plus un bogue est découvert plus le processus est cher, plus il est cher. Avec le modèle de générateur, il serait normal que la méthode de construction (dans votre exemple appelée getCar ()) lève une exception s'il manque des données requises.
Ken

7
+-------------------------------------------------------------------+---------------------------------------------------+
|                              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:

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

Courtoisie


5

Builder et Abstract Factory sont destinés à des fins différentes. Selon le bon cas d'utilisation, vous devez sélectionner un modèle de conception approprié.

Builder principales caractéristiques:

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

Caractéristiques saillantes d' usine ( usine simple):

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

Souvent, les conceptions commencent par utiliser la méthode Factory (moins compliquée, plus personnalisable, les sous-classes prolifèrent) et évoluent vers Abstract Factory , Prototype ou Builder (plus flexible, plus complexe)

Jetez un œil aux articles connexes:

Garder le constructeur dans une classe distincte (interface fluide)

Modèles de conception: méthode Factory vs Factory vs Abstract Factory

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

fabrication de source

journaldev


5

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

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


4

Les modèles Abstract Factory & Builder sont tous deux des modèles créatifs mais avec une intention différente.

Abstract Factory Pattern met l'accent sur la création d'objets pour les familles d'objets connexes 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.

Le modèle de générateur se concentre sur la construction d'un objet complexe, étape par étape. Il dissocie la représentation du processus de construction de l'objet complexe, de sorte que le même processus de construction peut ê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 de Builder, où le protocole définit toutes les étapes logiques requises pour créer l'objet complexe.

pouvez-vous s'il vous plaît expliquer le sens de "découpler la représentation du processus de construction de l'objet complexe"
Rajdeep

3

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

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

  1. Exemple: Cola, Big Mac, French Fries
  2. Exemple: Sprite, pépites, frites frisées

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

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 générateur, l'algorithme est encapsulé dans le directeur tandis que les générateurs sont utilisés pour créer les pièces intégrales. Faire varier le générateur utilisé dans l'algorithme du directeur entraîne une représentation différente car d'autres parties sont composées dans un menu. La façon dont un menu est créé reste la même.


1
Cela explique la "séparation de la construction d'un objet complexe de sa représentation"
Rajdeep

2

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

Exemple: disons que nous créons Maze

1. Usine abstraite:

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();
}

2

Je pense que l'utilisation et la différence entre les modèles Factory & Builder peuvent être comprises / clarifiées plus facilement dans une certaine période de temps car vous avez travaillé sur la même base de code et en changeant les exigences.

D'après mon expérience, vous commencez généralement par un modèle Factory comprenant quelques méthodes de création statiques pour masquer principalement une logique d'initialisation relativement complexe. Au fur et à mesure que votre hiérarchie d'objets devient plus complexe (ou que vous ajoutez plus de types, de paramètres), vous finirez probablement par avoir vos méthodes remplies avec plus de paramètres et sans oublier que vous devrez recompiler votre module Factory. Tout cela augmente la complexité de vos méthodes de création, diminue la lisibilité et fragilise le module de création.

Ce point sera peut-être le point de transition / extension. Ce faisant, vous créez un module wrapper autour des paramètres de construction , puis vous pourrez représenter de nouveaux objets (similaires) en ajoutant plus d'abstractions (peut-être) et d'implémentations sans toucher à votre logique de création. Vous avez donc eu une logique «moins» complexe.

Franchement, faire référence à quelque chose de "faire créer un objet en une ou plusieurs étapes est la différence" car le seul facteur de diversité n'était pas suffisant pour que je puisse les distinguer car je pouvais utiliser les deux façons pour presque tous les cas auxquels je faisais face. maintenant sans aucun avantage. Voilà donc ce que j'en ai finalement pensé.


2

Le principal avantage du modèle de générateur par rapport au modèle d'usine est dans le cas où vous souhaitez créer un objet standard avec de nombreuses personnalisations possibles, mais vous finissez généralement par en personnaliser quelques-unes.

Par exemple, si vous souhaitez écrire un client HTTP - vous allez configurer certains paramètres par défaut comme le délai d'écriture / lecture par défaut, les protocoles, le cache, DNS, les intercepteurs, etc.

La plupart des utilisateurs de votre client utiliseront simplement ces paramètres par défaut, tandis que d'autres utilisateurs voudront peut-être personnaliser certains des autres paramètres. Dans certains cas, vous souhaiterez simplement modifier les délais d'expiration et utiliser le reste tel quel, tandis que dans d'autres cas, vous devrez peut-être personnaliser par exemple le cache.

Voici les moyens possibles d'instancier votre client (extrait de OkHttpClient):

//just give me the default stuff
HttpClient.Builder().build()   

//I want to use custom cache
HttpClient.Builder().cache(MyCache()).build() 

//I want custom connection timeout
HttpClient.Builder().connectTimeout(30, TimeUnit.SECONDS).build() 

//I am more interested in read/write timeout
HttpClient.Builder()
        .readTimeout(30, TimeUnit.SECONDS)
        .writeTimeout(30, TimeUnit.SECONDS).build()

Si vous utilisez un modèle d'usine pour cela, vous finirez par écrire de nombreuses méthodes avec toutes les combinaisons possibles de paramètres de création. Avec le générateur, vous spécifiez simplement ceux qui vous intéressent et laissez le générateur le construire pour vous en prenant soin de tous ces autres paramètres.


1

Le modèle de construction met l'accent sur la complexité de la création d'un objet (résolu par des «étapes»)

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


1

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

Ici, la classe de générateur agit comme médiateur entre la classe principale et les classes de type spécifiques. Plus d'abstraction.


1

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


1

A mon humble avis

Builder est une sorte d'usine plus complexe.

Mais dans Builder, vous pouvez instancier des objets en utilisant d'autres usines , qui sont nécessaires pour construire un objet final et valide.

Donc, en parlant de l'évolution des "Patterns Créatifs" par complexité, vous pouvez y penser de cette façon:

Dependency Injection Container -> Service Locator -> Builder -> Factory

1

Les deux modèles viennent pour la même nécessité: cacher à un code client la logique de construction d'un objet complexe. Mais qu'est-ce qui rend un objet «complexe» (ou parfois compliqué)? 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, certains seront dans un état initial par défaut (simplement parce que nous aurions dû apprendre que définir une dépendance par défaut sur null n'est pas la manière la plus propre ) et un autre ensemble à un état déterminé par une condition. De plus, il existe des propriétés d'objet qui sont une sorte de "dépendances inconscientes", mais elles peuvent également prendre des états facultatifs.

il existe deux façons 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 conduisent à la construction du composant.

  • Polymorphisme: les règles de construction sont déclarées directement dans la définition de sous-type, vous avez donc un ensemble de règles pour chaque sous-type et une condition décide laquelle parmi ces règles s'applique pour construire l'objet. Une usine s'intègre parfaitement dans ce scénario.

Rien n'empêche de mélanger ces deux approches. Une famille de produits pourrait faire abstraction de la création d'objets effectuée avec un constructeur, un constructeur pourrait utiliser des usines pour déterminer quel objet composant instancier.


0

À mon avis, le modèle Builder est utilisé lorsque vous souhaitez créer un objet à partir d'un tas 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 permet de masquer la création de pièce au client pour rendre le constructeur et le client indépendants. Il est utilisé pour la création d'objets complexes (objets qui peuvent être constitués de propriétés compliquées)

Alors que le modèle d'usine spécifie que vous souhaitez créer des objets d'une famille commune et que vous souhaitez qu'il soit cerated à la fois. Il est utilisé pour des objets plus simples.


0

Constructeur et usine abstraite

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

Interface commune pour les produits

Dans la pratique, les produits créés par les constructeurs de béton ont une structure significativement différente, donc s'il n'y a pas de raison de dériver des produits différents, une classe parente commune. Cela distingue également le modèle Builder du modèle Abstract Factory qui crée des objets dérivés d'un type commun.

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


-2

Le modèle d'usine crée une implémentation concrète d'une classe au moment de l'exécution, c'est-à-dire que son intention principale est d'utiliser le polymorphisme pour permettre aux sous-classes de décider quelle classe instancier. Cela signifie qu'au moment de la compilation, nous ne connaissons pas la classe exacte qui sera créée, tandis que le modèle Builder est principalement concerné par la résolution du problème de l'antipattern des constructeurs télescopiques, qui se pose en raison du grand nombre de champs facultatifs d'une classe. Dans le modèle de générateur, il n'y a aucune notion de polymorphisme, car nous savons quel objet nous essayons de construire au moment de la compilation.

Le seul thème commun de ces deux modèles est le masquage des constructeurs et la création d'objets derrière les méthodes d'usine, et la méthode de construction, pour une construction d'objet améliorée.


-2

Le modèle d'usine vous permet de créer un objet à la fois tandis que le modèle de générateur vous permet d'interrompre le processus de création d'un objet. De cette façon, vous pouvez ajouter différentes fonctionnalités lors de la création d'un objet.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.