Modèles de conception: usine abstraite vs méthode D'usine

Remarque: les Questions sont à la fin du post.

j'ai lu les autres fils stackoverflow concernant usine abstraite vs méthode D'usine . Je comprends l'intention de chaque modèle. Toutefois, Je ne suis pas très clair sur la définition.

méthode D'usine définit une interface pour la création d'un objet, mais permet de les sous-classes décident lesquelles parmi celles instancier. Une méthode de fabrique laisser les classes reportent l'instanciation à les sous-classes.

par contraste, une usine abstraite fournit une interface pour la création de familles associées ou dépendantes objets sans spécifier leur les classes concrètes.

- Jean Feminella

Le Abstract Factory semble très similaire à la Méthode de Fabrique . J'ai dessiné quelques UML des cours pour illustrer mon point de vue.

Note:

  • le diagramme est de www.yuml.com donc ils ne sont pas parfaitement orientés. Mais ses un service gratuit :).
  • les diagrammes peuvent ne pas être parfaits. Je suis encore en train d'apprendre le GoF modèles de conception.

Méthode En Usine:

Factory Method

Abstract Factory (seulement 1 membre):

Abstract Factory (only 1 member)

Abstract Factory (plus de membres):

alt text

Questions:

  1. si le Abstract Factory n'a qu'un créateur et un produit, est-il toujours le modèle Abstract Factory ? (une interface pour créer des familles)
  2. Peut Méthode de Fabrique béton créateur être créé à partir d'une Interface ou d'-t-il à partir d'une classe? (class defer instanciations to subclasses)
  3. si l'usine abstraite ne peut avoir qu'un seul créateur et un seul produit, est la seule différence entre le Abstract Factory et le Méthode de Fabrique que le créateur de l'ancien est une Interface et le créateur pour le dernier de la Classe?
137
demandé sur Community 2010-11-18 01:25:07

10 réponses

Espérons que cette aide. Il décrit les différents types d'usines. J'ai utilisé Head First Design Patterns comme référence. J'ai utilisé yuml.me à diagramme.

Statique Usine

est une classe avec une méthode statique pour produire divers sous-types de produits.

Static Factory

Simple Usine

est une classe qui peut produire divers sous-types de produits. (C'est mieux que la Statique de l'Usine. Lorsque de nouveaux types sont ajoutés, la classe de produit de base n'a pas besoin d'être changée seulement la classe D'usine Simple)

Simple Factoryt

Méthode En Usine

contient une méthode pour produire un type de produit lié à ce type. (C'est mieux qu'une Simple Usine parce que le type est reporté à une sous-classe.)

Factory Method

Abstract Factory

produit une famille de Types apparentés. Il est sensiblement différent d'une méthode D'usine car il a plus d'une méthode des types qu'il produit. (Ceci est compliqué référez-vous au diagramme suivant pour un meilleur exemple de la vie réelle).

Abstract Factory

exemple tiré du cadre .NET

DbFactoriesProvider est une usine Simple car il n'a pas de sous-types. Le DbFactoryProvider est une usine abstraite car il peut créer divers objets de base de données connexes tels que des objets de connexion et de commande.

Abstract Factory From .NET Framework ​​​

127
répondu 1valdis 2018-02-21 15:45:54

les deux motifs sont certainement liés!

La différence entre les modèles est généralement dans l'intention.

le intent de Factory Method Est " définir une interface pour créer un objet, mais laisser les sous-classes décider quelle classe instantiate. Usine Méthode permet à une classe de reporter l'instanciation des classes."

Le intention de Abstract Factory est " fournir une interface pour créer des familles d'objets liés ou dépendants sans spécifier leurs classes concrètes."

basé purement sur ces déclarations d'intention (Cité de GoF), je dirais qu'en effet méthode D'usine est en quelque sorte un" dégénéré " usine abstraite avec une famille d'un.

ils ont généralement tendance à différer dans la mise en œuvre, comme Méthode d'usine est beaucoup plus simple que usine abstraite .

ils sont également liés dans la mise en œuvre cependant. Comme indiqué dans le Livre de GoF,

AbstractFactory déclare seulement une interface pour créer des produits. C'est à des sous-classes de produits concrets de les créer. La façon la plus courante de le faire est de définir une méthode de fabrique pour chaque produit.

Ce c2 wiki a également une discussion intéressante sur ce sujet.

74
répondu Don Roby 2013-03-10 17:32:39

il semble que la liste des (excellentes) questions de L'OP ait été ignorée. Les réponses actuelles offrent simplement des définitions remaniées. Je vais donc tenter de répondre de façon concise aux questions initiales.

  1. si la Abstract Factory n'a qu'un créateur et un produit, est-ce encore le Abstract Factory pattern? (une interface pour creating familles)

Non . Une usine abstraite doit créer plus d'un produit pour faire une "famille de produits connexes". L'exemple canonique GoF crée ScrollBar() et Window() . L'avantage (et le but) est que L'usine abstraite peut imposer un thème commun à travers ses multiples produits.

  1. Peut-On créer le méthode D'usine créateur de béton à partir D'une Interface ou est-ce que ça doit venir d'une classe? (classes de reporter les instanciations de sous-classes)

tout d'abord, nous devons noter que ni Java ni C# existait lorsque le GoF a écrit leur livre. L'utilisation du terme interface par les GEF n'est pas liée aux types d'interface introduits par des langages particuliers. Par conséquent, le créateur concret peut être créé à partir de n'importe quelle API. Le point important dans le modèle est que L'API consomme sa propre usine Méthode, donc une interface avec une seule méthode ne peut pas être une méthode D'usine plus qu'elle peut être une usine abstraite.

  1. si l'usine abstraite ne peut avoir qu'un seul créateur et un seul produit, est la seule différence entre le usine abstraite et le Méthode de Fabrique que le créateur de l'ancien est une Interface et le créateur pour le dernier de la Classe?

cette question n'est plus valable, suite aux réponses ci-dessus; cependant, si vous êtes laissé penser que la seule différence entre la méthode abstraite de L'usine et de L'usine est le nombre de produits créés, considérez comment un client consomme chacun de ces modèles. Une usine abstraite est typiquement injectée dans son client et invoquée par composition/délégation. Une Méthode de Fabrique doit être héritée. Tout revient donc à l'ancien débat entre composition et héritage.

Mais ces réponses ont soulevé une quatrième question!

  1. car, une interface avec une seule méthode ne peut pas être une méthode D'usine pas plus qu'elle ne peut être une usine abstraite , ce que nous appelons interface créative avec une seule méthode?

Si la méthode est statique, il est communément appelé un Usine Statique . Si la méthode n'est pas statique, elle est communément appelée une usine Simple . Ni l'un ni l'autre n'est un modèle GoF, mais dans la pratique, ils sont beaucoup plus couramment utilisés!

12
répondu jaco0646 2016-07-29 22:17:01

À mon avis, la légère différence entre les deux modèles réside dans le applicabilité , et donc, comme déjà dit, dans le Intention .

récapitulons les définitions (toutes deux de Wikipedia).

Abstract Factory

Fournir une interface pour la création de familles de ou des objets dépendants sans préciser leurs classes concrètes.

Méthode En Usine

définit une" interface 151910920 "pour créer un objet , mais laissons aux classes qui implémentent l'interface de décider quelle classe instancier . La méthode permet à une classe de reporter l'instanciation des classes.

les deux modèles permettent de découpler le l'utilisateur s'oppose à la création d'instances nécessaires (découplage de l'exécution), et c'est l'aspect le plus courant. Les deux modèles permettent de créer une hiérarchie des usines en fonction de besoins spécifiques, et c'est un autre aspect commun.

Abstract Factory permet de créer plusieurs types d'instances différentes dans une sous-classe, et de particulariser le comportement des créations dans ses différentes sous-classes; normalement, la méthode Factory déclare la création d'un seul type d'objet qui peut être particularisées selon le sous-classement mécanisme. C'est toute la différence.

En les résumant. Disons que le produit définit la super-classe des objets de création, et que ProductA et ProductB sont deux sous-classes différentes. Par conséquent, la méthode abstraite D'usine aura deux méthodes, createProductA () et createProductB () qui seront particularisées (en termes d'étapes de création) dans ses sous-classes spécifiques: les sous-classes d'usine particularisent le étapes de création pour les deux classes définies d'objets en cours de création.

selon l'exemple ci-dessus, la méthode D'usine sera mise en œuvre différemment, en faisant abstraction de la création de ProductA et de ProductB dans autant d'usines (une méthode par usine), et la spécialisation supplémentaire du étapes de création sera déléguée à la hiérarchie comme il est construit.

4
répondu Paolo Maresca 2014-04-28 09:29:30

si j'ai créé un Abstrait (référencé via une interface ou une classe de base abstraite) Classe D'usine qui crée des objets qui n'ont qu'une seule méthode pour créer des objets, alors ce serait une méthode D'usine .

si L'usine abstraite avait plus d'une méthode pour créer des objets, alors ce serait une usine abstraite .

disons que je fais un Manager qui s'occupera du les besoins des méthodes d'action pour un contrôleur MVC. Si elle avait une méthode, disons pour créer les objets moteur qui seront utilisés pour créer des modèles de vue, alors ce serait un modèle de méthode d'usine. D'un autre côté, s'il y avait deux méthodes: l'une pour créer des moteurs de modèles de vue, et l'autre pour créer des moteurs de modèles d'action (ou ce que vous voulez appeler le modèle que la méthode d'action contient des consommateurs), alors ce serait une usine abstraite.

public ActionResult DoSomething(SpecificActionModel model)
{
    var actionModelEngine = manager.GetActionModelEngine<SpecificActionModel>();
    actionModelEngine.Execute(SpecificActionModelEnum.Value);

    var viewModelEngine = manager.GetViewModelEngine<SpecificViewModel>();
    return View(viewModelEngine.GetViewModel(SpecificViewModelEnum.Value);
}
2
répondu Christopher Stevenson 2013-10-15 14:16:48

bien que, il a été de nombreuses années depuis les gens de StackOverflow interrogés sur cette question de la même façon dans d'autres postes (le plus ancien va à 2009), Je ne pouvais toujours pas trouver la réponse que je voulais.


donc j'ai fait quelques heures de recherches à travers le web, en passant en revue les exemples, et en est venu à cette conclusion, les principales différences de L'usine abstraite de la méthode D'usine sont

  • L'intention: cohérence ou "look-and-feel" : Résumé de l'Usine intention est de regrouper une famille d'objets avec un même style (ex. mêmes widgets D'interface utilisateur, même style de pièces de voiture, objets d'un même système D'exploitation,etc.) Beaucoup exemples tirés de Abstract Factory mentionne l'Expression Clé "le même look-and-feel".
  • d'Objets formant un grand groupe d'objets : Abstract Factory crée une famille d'objets formant un grand groupe d'objets, pas un objet unique.
  • plus tard, ajouter un nouveau style : si nous avons continué à utiliser la méthode de L'usine et essayer d'ajouter un nouvel ensemble de style à l'infrastructure existante, il serait douloureux. Avec Abstract Factory, tous nous devons simplement créer une nouvelle usine de béton qui implémente la classe industrielle abstraite.

Le comptoir des exemples serait

  • pièce de voiture pour voiture de sport utilisée dans une berline. Cette incohérence peut entraîner des accidents.
  • un bouton de style Windows dans différents widgets D'interface graphique OS. Ça ne va rien casser à part blesser l'expérience utilisateur pour certaines personnes, comme moi.
  • plus tard, nous découvrez que notre logiciel a besoin d'exécuter la prochaine mise à niveau du système D'exploitation qui a besoin d'un ensemble différent d'objets système compatibles tout en maintenant le logiciel compatible en arrière.

par conséquent, quand un groupe d'objet final devrait avoir le même style sans exception d'un objet et vous voulez cacher ce détail "garder le même style", alors nous devrions utiliser usine abstraite.

1
répondu Andrew Chong 2017-05-23 12:02:51

pour autant que je comprenne la signification des définitions abstraites des méthodes usine et usine, la première est implémentée dans un contexte statique et fournit un objet basé sur des paramètres d'entrée.

Second one utilise l'objet déjà créé (la famille) qui implémente l'interface de méthode d'usine. La méthode de fabrique puis crée une instance spécifique liée à l'objet original, n'importe lequel.

donc cela conduit généralement à utiliser les deux modèles ensemble où dans la première étape vous créez un objet général qui décrit la famille d'objets liés. Il est appelé par la méthode statique méthode getInstance("mon nom de famille"). La mise en œuvre d'une telle méthode getInstance décide quel objet de la famille sera créé.

ensuite j'appelle la méthode createProduct() sur l'objet familial nouvellement créé et en fonction de l'objet familial le nouveau produit sera retourné.

il semble que ces modèles coopèrent à chacun.

en d'autres mots Abstract Factory se concentre sur" ce qui "sera créé et la méthode D'usine" comment " il sera créé.

0
répondu Jan Stanicek 2013-06-18 11:35:53

il suffit de se rappeler qu'une usine abstraite est une usine qui peut retourner plusieurs usines . Donc si vous aviez une AnimalSpeciesFactory il peut retourner des usines comme celle-ci:

Mamalfactory,BirdFactory,Fishfactory, ReptileFactory. Maintenant que vous avez une seule usine à partir du AnimalSpeciesFactory, ils utilisent le modèle d'usine pour créer des objets spécifiques. Par exemple, imaginez que vous avez obtenu un répertoire de ce répertoire AnimalFactory, puis vous pouvez proposer de créer des objets reptiles comme: Serpents, tortues, objets lézards.

0
répondu j2emanue 2016-02-08 16:52:20

Factory method pattern est un dessin créatif qui traite de la création d'objets sans montrer la classe exacte de l'objet qui est créé. Ce modèle permet essentiellement une classe reporte l'instanciation de sous-classes.

le dessin abstrait D'usine sert d'encapsulation à un groupe d'usines individuelles sans exposer les classes de béton. Dans ce modèle, une interface générique d'une classe d'usine abstraite est utilisée pour créer objet concret requis séparant les détails de mise en œuvre des objets de leur utilisation et de leur composition. Ce modèle de conception est largement utilisé dans les applications GUI où le type similaire de composants GUI doit être créé.

tout en cherchant sur google je suis venu en suivant blog qui a expliqué les deux motif de conception brillamment. regardez ces

http://simpletechtalks.com/factory-design-pattern /

http://simpletechtalks.com/abstract-factory-design-pattern /

0
répondu Neo 2016-12-28 11:24:02
/*
//Factory methods:

//1. Factory Method - Abstract Creator Class



#include <iostream>
#include <string.h>
using namespace std;

const std::string nineNintyCC = std::string("990CC");
const std::string thousandTwoHundredCC = std::string("1200CC");
const std::string ThousandFiveHundredCC = std::string("1500CC");
const std::string fiveThousandCC = std::string("5000CC");

// Product
class Engine
{
    public:
    virtual void packEngine() = 0;  
};

// Concrete products
// concrete product class one
class C990CCEngine: public Engine
{

    public:
    void packEngine()
    {
       cout << "Pack 990CC engine" << endl;   
    }
};

// concrete class Two
class C1200CCEngine: public Engine
{   public:
    void packEngine()
    {
        cout << "pack 1200CC engine" << endl;
    }

};

// Concrete class Three
class C1500CCEngine: public Engine
{
    public:
    void packEngine()
    {
        cout << "Pack 1500CC engine" << endl;
    }

};


// Car Factory:
class CarFactory{
    public:

    virtual Engine* createEngine(const std::string& type) = 0;
};
class Factory: public CarFactory
{
    public:
     Engine *createEngine(const std::string& type)
     {

          if(0 == nineNintyCC.compare(type))
          {    
             return new C990CCEngine;
          }
          else if(0 == thousandTwoHundredCC.compare(type))
          {
             return new C1200CCEngine;
          }
          else if(0 == ThousandFiveHundredCC.compare(type))
          {
             return new C1500CCEngine;
          } 
          else
           {
                 cout << "Invalid factory input" << endl;
             return NULL;
           }
           return NULL;
     }
};

int main()
{

    CarFactory* ptr = new Factory;
    Engine*pEngine =  ptr->createEngine(nineNintyCC);
    if(pEngine)
    {
        pEngine->packEngine();
        delete pEngine;
    }
    else
    {
        cout << "No engine exists of your type in our factory" << endl;
    }
    pEngine =  ptr->createEngine(ThousandFiveHundredCC);
    if(pEngine)
    {
        pEngine->packEngine();
        delete pEngine;
    }
    else
    {
        cout << "No engine exists of your type in our factory" << endl;
    }
    pEngine =  ptr->createEngine(thousandTwoHundredCC);
    if(pEngine)
    {
        pEngine->packEngine();
        delete pEngine;
    }
    else
    {
        cout << "No engine exists of your type in our factory" << endl;
    }
    pEngine = ptr-> createEngine(fiveThousandCC);
    if(pEngine)
    {
        pEngine->packEngine();
        delete pEngine;
    }
    else
    {
        cout << "No engine exists of your type in our factory" << endl;
    }
    return 0;
}

*/
/*
//
// interface product
#include <iostream>
#include <string>
using namespace std;

class Engine
{
 public:
 virtual void EngineType() = 0;

};

// concrte product
class AltoEngine: public Engine
{
  public:
  void EngineType()
  {
      cout << "Alto Engine" << endl;
  }
};

//Concrte product
class SwiftEngine : public Engine
{
    public:
    void EngineType()
    {
        cout << "Swift Engine" << endl;    
    }
};

class Body
{
   public:
    virtual void bodyType() = 0;

};

class AltoBody: public Body
{
  public:  
    virtual void bodyType()
    {
        cout << "Alto Car Body" << endl;
    }
};

class SwiftBody : public Body
{
    public:
    void bodyType()
    {
        cout << "SwiftCar Body" << endl;
    }

};


class CarFactory
{
   public:
   virtual Engine* createEngineProduct() = 0;
   virtual Body*   createBodyPoduct() = 0;
};
class AltoCarFactory: public CarFactory
{
    public:
    Engine * createEngineProduct()
    {
        return new AltoEngine;
    }
    Body* createBodyPoduct()
    {
        return new AltoBody;
    }

};

class SwiftCarFactory: public CarFactory
{
    public:
    Engine * createEngineProduct()
    {
        return new SwiftEngine;
    }
    Body* createBodyPoduct()
    {
        return new SwiftBody;
    }

};

int main()
{

    CarFactory* pAltoFactory = new AltoCarFactory;
    Engine* pAltoEngine = pAltoFactory->createEngineProduct();
    pAltoEngine->EngineType();
    Body* pAltoBody = pAltoFactory->createBodyPoduct();
    pAltoBody->bodyType();



    CarFactory* pSwiftFactory = NULL;
    pSwiftFactory = new SwiftCarFactory;
    Engine* pSwiftEngine = pSwiftFactory->createEngineProduct();
    pSwiftEngine->EngineType();
    Body* pSwfitBody = pSwiftFactory->createBodyPoduct();
    pSwfitBody->bodyType();
    delete pAltoBody;
    delete pAltoFactory;
    delete pSwfitBody;
    delete pSwiftFactory;
    return 0;
}
*/

/*

// One more Factory example;

#include <iostream>
#include <string>
using namespace std;

const std::string maruthi = std::string("Maruthi");
const std::string fiat = std::string("Fiat");
const std::string renault = std::string("Renault");
// Interface
class CarEngine
{
 public:
    virtual void engineType() = 0;
};

// Concrete class
class FiatEngine: public CarEngine
{
  public:
  void engineType()
  {
      cout << "Fait Engine Engine" << endl;
  }

};
// ConcreteClass
class RenaultEngine : public CarEngine
{
    public:
    void engineType()
    {
        cout << "Renault Engine" << endl;
    }

};
// Concrete class
class MaruthiEngine : public CarEngine
{
    public:
    void engineType()
    {
        cout << "Maruthi Engine" << endl;
    }
};


// Factory
class CarFactory
{
    public:
    virtual CarEngine* createFactory(const std::string&) = 0;
};

// EngineFactory
class CarEngineFactory : public CarFactory
{
     public:
     CarEngine* createFactory(const std::string&  type)
     {
          if(0 == maruthi.compare(type))
          {
              return new MaruthiEngine;

          }
          else if(0 == fiat.compare(type))
          {
              return  new FiatEngine;
          }
          else if(0 == renault.compare(type))
          {
              return new RenaultEngine;
          }
          else
          {
              cout << "Invalid Engine type" << endl;
              return NULL;
          }
     }

  };

int main()
{
    CarFactory* pCarFactory = new CarEngineFactory;
    CarEngine* pMaruthiCarEngine = pCarFactory->createFactory(maruthi);
    pMaruthiCarEngine->engineType();

    CarEngine* pFiatCarEngine = pCarFactory->createFactory(fiat);
    pFiatCarEngine->engineType();


    CarEngine* pRenaultCarEngine = pCarFactory->createFactory(renault);
    pRenaultCarEngine->engineType();

    return 0;
}


*/


/*

// One more Factory example;

#include <iostream>
#include <string>
using namespace std;

const std::string maruthi = std::string("Maruthi");
const std::string fiat = std::string("Fiat");
const std::string renault = std::string("Renault");


// Interface
class CarEngine
{
 public:
    virtual void engineType() = 0;
};

// Concrete class
class FiatEngine: public CarEngine
{
  public:
  void engineType()
  {
      cout << "Fait Car Engine" << endl;
  }

};

// ConcreteClass
class RenaultEngine : public CarEngine
{
    public:
    void engineType()
    {
        cout << "Renault Car Engine" << endl;
    }

};

// Concrete class
class MaruthiEngine : public CarEngine
{
    public:
    void engineType()
    {
        cout << "Maruthi Car Engine" << endl;
    }
};

// Interface
class CarBody
{
 public:
    virtual void bodyType() = 0;
};

// Concrete class
class FiatBody: public CarBody
{
  public:
  void bodyType()
  {
      cout << "Fait car Body" << endl;
  }

};

// ConcreteClass
class RenaultBody : public CarBody
{
    public:
    void bodyType()
    {
        cout << "Renault Body" << endl;
    }

};

// Concrete class
class MaruthiBody : public CarBody
{
    public:
    void bodyType()
    {
        cout << "Maruthi body" << endl;
    }
};


// Factory
class CarFactory
{
    public:
    virtual CarEngine* createCarEngineProduct() = 0;
    virtual CarBody* createCarBodyProduct() = 0;
};

// FiatFactory
class FaitCarFactory : public CarFactory
{
     public:
     CarEngine* createCarEngineProduct()
     {
        return new FiatEngine; 
     }
     CarBody* createCarBodyProduct()
     {
         return new FiatBody;
     }
};

// Maruthi Factory
class MaruthiCarFactory : public CarFactory
{
     public:
     CarEngine* createCarEngineProduct()
     {
         return new MaruthiEngine;
     }
     CarBody* createCarBodyProduct()
     {
         return new MaruthiBody;
     }

};

// Renault Factory
class RenaultCarFactory : public CarFactory
{
     public:
    CarEngine* createCarEngineProduct()
    {
        return new RenaultEngine;
    }

    CarBody* createCarBodyProduct()
    {
        return new RenaultBody;
    }

};


int main()
{

   // Fiat Factory
   CarFactory* pFiatCarFactory = new FaitCarFactory;
   CarEngine* pFiatEngine = pFiatCarFactory->createCarEngineProduct();
   CarBody*  pFiatBody = pFiatCarFactory->createCarBodyProduct();
   pFiatEngine->engineType();
   pFiatBody->bodyType();

   // Renault Car Factory
    return 0;
}

*/
0
répondu user1573259 2018-04-25 16:56:08