582 votes

Quelles sont les différences entre les patrons de conception Abstract Factory et Factory ?

Je sais qu'il existe de nombreux articles sur les différences entre ces deux modèles, mais il y a quelques éléments que je ne trouve pas.

D'après ce que j'ai lu, je vois que le modèle de méthode factory permet de définir comment créer un seul produit concret, tout en cachant l'implémentation au client, qui verra un produit générique. Ma première question concerne l'usine abstraite. Son rôle est-il de vous permettre de créer des familles d'objets concrets (qui peuvent dépendre de la fabrique spécifique que vous utilisez) plutôt qu'un seul objet concret ? La fabrique abstraite ne renvoie-t-elle qu'un seul très gros objet ou plusieurs objets en fonction des méthodes que vous appelez ?

Mes deux dernières questions portent sur une seule citation que je n'arrive pas à comprendre entièrement et que j'ai vue à de nombreux endroits :

Une différence entre les deux est que avec le modèle Abstract Factory, une classe délègue la responsabilité de l'instanciation d'un objet à un autre objet via la composition, alors que le modèle Factory Method utilise l'héritage et s'appuie sur une sous-classe pour gérer la l'instanciation de l'objet souhaité.

Si j'ai bien compris, le modèle de méthode d'usine possède une interface Creator qui fait que le ConcreteCreator est chargé de savoir quel ConcreteProduct instancier. Est-ce cela que signifie l'utilisation de l'héritage pour gérer l'instanciation des objets ?

Maintenant, en ce qui concerne cette citation, comment exactement le modèle Abstract Factory délègue-t-il la responsabilité de l'instanciation de l'objet à un autre objet via la composition ? Qu'est-ce que cela signifie ? À mes yeux, il semble que le modèle Abstract Factory utilise également l'héritage pour effectuer le processus de construction, mais là encore, je suis toujours en train d'apprendre à connaître ces modèles.

Toute aide, en particulier pour la dernière question, serait grandement appréciée.

4 votes

0 votes

Voir "comment l'instance a été créée" du point de vue du client, vous aiderait à comprendre le devis.

4 votes

@nawfal, les réponses dans ce fil sont affreuses.

639voto

Tom Dalling Points 10656

La différence entre les deux

La principale différence entre une "méthode d'usine" et une "usine abstraite" est que la méthode d'usine est une méthode, et qu'une usine abstraite est un objet. Je pense que beaucoup de gens confondent ces deux termes, et commencent à les utiliser de manière interchangeable. Je me souviens que j'ai eu du mal à trouver exactement la différence lorsque je les ai appris.

Comme la méthode factory n'est qu'une méthode, elle peut être surchargée dans une sous-classe, d'où la seconde moitié de votre citation :

... le modèle Factory Method utilise l'héritage et s'appuie sur une sous-classe pour gérer l'instanciation de l'objet l'instanciation de l'objet.

La citation suppose qu'un objet appelle son propre méthode d'usine ici. Par conséquent, la seule chose qui pourrait modifier la valeur de retour serait une sous-classe.

L'usine abstraite est un objet qui a plusieurs méthodes d'usine sur lui. En regardant la première moitié de votre citation :

... avec le modèle Abstract Factory, une classe délègue la responsabilité de l'objet l'instanciation d'un objet à un autre objet via composition ...

Ce qu'ils disent, c'est qu'il y a un objet A, qui veut créer un objet Foo. Au lieu de créer l'objet Foo lui-même (par exemple, avec une méthode d'usine), il va obtenir un objet de type différents (la fabrique abstraite) pour créer l'objet Foo.

Exemples de codes

Pour vous montrer la différence, voici une méthode d'usine en cours d'utilisation :

class A {
    public void doSomething() {
        Foo f = makeFoo();
        f.whatever();   
    }

    protected Foo makeFoo() {
        return new RegularFoo();
    }
}

class B extends A {
    protected Foo makeFoo() {
        //subclass is overriding the factory method 
        //to return something different
        return new SpecialFoo();
    }
}

Et voici une fabrique abstraite en cours d'utilisation :

class A {
    private Factory factory;

    public A(Factory factory) {
        this.factory = factory;
    }

    public void doSomething() {
        //The concrete class of "f" depends on the concrete class
        //of the factory passed into the constructor. If you provide a
        //different factory, you get a different Foo object.
        Foo f = factory.makeFoo();
        f.whatever();
    }
}

interface Factory {
    Foo makeFoo();
    Bar makeBar();
    Aycufcn makeAmbiguousYetCommonlyUsedFakeClassName();
}

//need to make concrete factories that implement the "Factory" interface here

40 votes

C'est une très bonne explication. Mais la partie la plus importante reste sans réponse, à savoir : quand utiliser l'un et l'autre modèle ?

21 votes

Je ne suis pas sûr que ce soit correct. Je suis presque sûr que Factory Method est un modèle de conception nommé après des méthodes d'usine, mais implique la structure des classes et l'héritage. Il ne s'agit pas d'une méthode unique.

3 votes

Il est donc correct de dire que la méthode Factory peut être une méthode dans toutes les classes ordinaires avec des objectifs différents. Mais l'Abstract Factory est une classe/objet utilisée par un client et est SEULEMENT responsable de la création de certains produits dans une famille ?

148voto

jgauffin Points 51913

Usine abstraite crée une classe de base avec des méthodes abstraites définissant des méthodes pour les objets qui doivent être créés. Chaque classe d'usine qui dérive la classe de base peut créer sa propre implémentation de chaque type d'objet.

enter image description here

Méthode d'usine est une simple méthode utilisée pour créer des objets dans une classe. Elle est généralement ajoutée dans la racine de l'agrégat (le Order a une méthode appelée CreateOrderLine )

enter image description here

Usine abstraite

Dans l'exemple ci-dessous, nous concevons une interface permettant de découpler la création de files d'attente d'un système de messagerie et de créer ainsi des implémentations pour différents systèmes de files d'attente sans avoir à modifier la base de code.

interface IMessageQueueFactory
{
  IMessageQueue CreateOutboundQueue(string name);
  IMessageQueue CreateReplyQueue(string name);
}

public class AzureServiceBusQueueFactory : IMessageQueueFactory
{
      IMessageQueue CreateOutboundQueue(string name)
      {
           //init queue
           return new AzureMessageQueue(/*....*/);
      }

      IMessageQueue CreateReplyQueue(string name)
      {
           //init response queue
           return new AzureResponseMessageQueue(/*....*/);
      }

}

public class MsmqFactory : IMessageQueueFactory
{
      IMessageQueue CreateOutboundQueue(string name)
      {
           //init queue
           return new MsmqMessageQueue(/*....*/);
      }

      IMessageQueue CreateReplyQueue(string name)
      {
           //init response queue
           return new MsmqResponseMessageQueue(/*....*/);
      }
}

Méthode d'usine

Le problème des serveurs HTTP est que nous avons toujours besoin d'une réponse pour chaque demande.

public interface IHttpRequest
{
    // .. all other methods ..

    IHttpResponse CreateResponse(int httpStatusCode);
}

Sans la méthode factory, les utilisateurs du serveur HTTP (c'est-à-dire les programmeurs) seraient contraints d'utiliser des classes spécifiques à l'implémentation, ce qui irait à l'encontre de l'objectif de l'initiative IHttpRequest interface.

C'est pourquoi nous introduisons la méthode factory afin que la création de la classe de réponse soit également abstraite.

Résumé

La différence est que le but recherché de la classe contenant une méthode d'usine n'est pas de créer des objets alors qu'une fabrique abstraite ne doit être utilisée que pour créer des objets.

Il faut faire attention lors de l'utilisation de méthodes d'usine car il est facile de casser le LSP ( Principe de substitution de Liskov ) lors de la création d'objets.

4 votes

Pourquoi avons-nous besoin d'un produit concret ?

93 votes

Parce que personne ne veut investir dans les idées.

6 votes

L'usine abstraite devrait créer plus que juste Button() pour créer une "famille de produits apparentés". Par exemple, l'exemple canonique de GoF crée ScrollBar() et Window() . L'avantage est que l'usine abstraite peut imposer un thème commun à ses multiples produits.

134voto

Vibha pandey Points 271

Les différences entre les modèles de conception AbstractFactory et Factory sont les suivantes :

  • Méthode d'usine est utilisé pour créer un seul produit mais Usine abstraite consiste à créer des familles de produits connexes ou dépendants.
  • Méthode d'usine expose une méthode au client pour créer l'objet, alors que dans le cas du modèle Usine abstraite ils exposent une famille d'objets connexes qui peuvent être constitués de ces méthodes Factory.
  • Méthode d'usine cache la construction d'un seul objet alors que Usine abstraite cache la construction d'une famille d'objets apparentés. Les fabriques abstraites sont généralement implémentées en utilisant (un ensemble de) méthodes de fabrique.
  • Usine abstraite utilise la composition pour déléguer la responsabilité de la création d'un objet à une autre classe tout en Méthode d'usine Le modèle de conception utilise l'héritage et s'appuie sur une classe ou une sous-classe dérivée pour créer un objet.
  • L'idée derrière le Méthode d'usine est qu'il permet d'envisager le cas où un client ne sait pas quelles classes concrètes il devra créer au moment de l'exécution, mais veut simplement obtenir une classe qui fera le travail tout en Usine abstraite est utilisé de préférence lorsque votre système doit créer plusieurs familles de produits ou lorsque vous souhaitez fournir une bibliothèque de produits sans exposer les détails de leur mise en œuvre !

Mise en œuvre du modèle de méthode d'usine : Factory Method UML

Implémentation du modèle de fabrique abstraite :

Abstract Factory UML

17 votes

Mmm, je ne suis pas sûr de l'exemple de la fabrique abstraite. Je pense que la fabrique de forme et la fabrique de couleur devraient implémenter les mêmes méthodes. Mais si j'ai raison, alors l'exemple n'a aucun sens.

4 votes

Les points sont corrects ; cependant, les deux diagrammes sont complètement faux et très trompeurs. Voir le diagramme ci-dessous de @Trying pour un modèle précis d'Abstract Factory.

1 votes

Je dois reconnaître que les deux diagrammes sont très trompeurs. Je les ai vus sur le site de Tutorialpoint et pour être honnête je ne suis pas 100% d'accord avec eux. Les descriptions semblent bonnes cependant

77voto

jaco0646 Points 702

La principale différence entre Abstract Factory et Factory Method est que L'usine abstraite est mise en œuvre par la composition mais La méthode Factory est mise en œuvre par l'héritage .

Oui, vous avez bien lu : la principale différence entre ces deux modèles est l'ancien composition vs héritage débat.

Les diagrammes UML se trouvent dans le livre (GoF). Je veux fournir des exemples de code, car je pense que la combinaison des exemples des deux premières réponses de ce fil de discussion donnera une meilleure démonstration que l'une ou l'autre réponse seule. De plus, j'ai utilisé la terminologie du livre dans les noms de classes et de méthodes.

Usine abstraite

  1. Le point le plus important à saisir ici est que la fabrique abstraite est injecté dans le client. C'est pourquoi nous disons que Abstract Factory est implémentée par Composition. Souvent, un cadre d'injection de dépendances dépendance effectuerait cette tâche, mais un cadre n'est pas nécessaire pour l'ID. pour l'ID.
  2. Le deuxième point critique est que les usines de béton ici sont pas Implémentations de la méthode Factory ! Un exemple de code pour la méthode Factory est présenté ci-dessous.
  3. Et enfin, le troisième point à noter est la relation entre le produits : dans ce cas, les files d'attente de sortie et de réponse. Une usine concrète fabrique concrète produit les files d'attente Azure, l'autre MSMQ. Le GdF fait référence à cette relation entre les produits comme une "famille" et il est important d'être Il est important de savoir que dans ce cas, famille ne signifie pas hiérarchie de classe.

    public class Client { private final AbstractFactory_MessageQueue factory;

    public Client(AbstractFactory_MessageQueue factory) {
        // The factory creates message queues either for Azure or MSMQ.
        // The client does not know which technology is used.
        this.factory = factory;
    }
    
    public void sendMessage() {
        //The client doesn't know whether the OutboundQueue is Azure or MSMQ.
        OutboundQueue out = factory.createProductA();
        out.sendMessage("Hello Abstract Factory!");
    }
    
    public String receiveMessage() {
        //The client doesn't know whether the ReplyQueue is Azure or MSMQ.
        ReplyQueue in = factory.createProductB();
        return in.receiveMessage();
    }

    }

    public interface AbstractFactory_MessageQueue { OutboundQueue createProductA(); ReplyQueue createProductB(); }

    public class ConcreteFactory_Azure implements AbstractFactory_MessageQueue { @Override public OutboundQueue createProductA() { return new AzureMessageQueue(); }

    @Override
    public ReplyQueue createProductB() {
        return new AzureResponseMessageQueue();
    }

    }

    public class ConcreteFactory_Msmq implements AbstractFactory_MessageQueue { @Override public OutboundQueue createProductA() { return new MsmqMessageQueue(); }

    @Override
    public ReplyQueue createProductB() {
        return new MsmqResponseMessageQueue();
    }

    }

Méthode d'usine

  1. Le point le plus important à saisir ici est que la ConcreteCreator est le client. En d'autres termes, le client est une sous-classe dont le parent définit la fonction factoryMethod() . C'est pourquoi nous disons que La méthode Factory est mise en œuvre par l'héritage.
  2. Le deuxième point critique est de se rappeler que le modèle Factory Method n'est rien d'autre qu'une spécialisation du modèle Template Method Pattern. Les deux modèles partagent une structure identique. Ils ne Ils ne diffèrent que par leur objectif. La méthode Factory est créative (elle construit quelque chose) alors que la méthode Template est comportementale (elle calcule quelque chose).
  3. Et enfin, le troisième point à noter est que la Creator (parent) invoque sa propre classe factoryMethod() . Si on enlève anOperation() de la classe parente, en ne laissant qu'une seule méthode derrière, il ne s'agit plus du modèle Factory Method. En d'autres termes, Factory Method ne peut pas être mis en œuvre avec moins de deux méthodes dans la classe parente ; et l'une doit invoquer l'autre.

    public abstract class Creator { public void anOperation() { Product p = factoryMethod(); p.whatever(); }

    protected abstract Product factoryMethod();

    }

    public class ConcreteCreator extends Creator { @Override protected Product factoryMethod() { return new ConcreteProduct(); } }

Patrons d'usine divers et variés

Sachez que, bien que le GoF définisse deux modèles d'usine différents, ce ne sont pas les seuls modèles d'usine qui existent. Ce ne sont même pas nécessairement les patrons Factory les plus utilisés. Un troisième exemple célèbre est le Static Factory Pattern de Josh Bloch dans Effective Java. Le livre Head First Design Patterns inclut encore un autre modèle qu'il appelle Simple Factory.

Ne tombez pas dans le piège de supposer que chaque modèle de l'usine doit correspondre à un modèle du GdF.

43voto

Trying Points 4092

Abstract Factory est une interface pour créer des produits connexes, mais Factory Method est seulement une méthode. Abstract Factory peut être implémenté par plusieurs Factory Methods.

Abstract Factory UML

11 votes

Vous avez déjà posté la même réponse ici . Si vous pensez que cette question est similaire, signalez-la plutôt comme un doublon.

0 votes

Très clair. Cette réponse devrait être choisie comme réponse à cette question. La réponse actuellement choisie comporte des explications redondantes.

2 votes

La deuxième légende du diagramme devrait être la suivante : " ces deux peut être méthodes d'usine". Sans voir les implémentations, nous ne savons pas si elles adhèrent ou non au pattern Factory Method. On croit souvent à tort que les méthodes d'une fabrique abstraite sont automatiquement des méthodes de fabrique. Ce n'est pas le cas. Il existe deux patterns GoF distincts pour une raison : ils sont implémentés différemment.

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