Question

Disons que j'ai un cours comme celui-ci:

class MonkeyFish
{
   MonkeyFish( GlobalObjectA & a, GlobalObjectB & b, GlobalObjectC & c);

   private:
     GlobalObjectA & m_a;
     GlobalObjectB & m_b;
     GlobalObjectC & m_c;
}

Sans usine, je dois procéder comme suit pour instancier un MonkeyFish .

GlobalObjectA a;
GlobalObjectB b;
GlobalObjectC c;

int main()
{
  MonkeyFish * monkey_fish = new MonkeyFish(a, b, c);
  monkey_fish->go();
}

Par contre, si j'ai un MonkeyFishFactory , il me semble que je dois le faire:

GlobalObjectA a;
GlobalObjectB b;
GlobalObjectC c;

int main()
{
  MonkeyFishFactory mf_factory(a, b, c);
  MonkeyFish * monkey_fish = mf_factory.buildMonkeyFish("Bob");
  monkey_fish->go();
}
  1. J'ai encore des objets globaux.

  2. Même si MonkeyFishFactory a lui-même créé le GlobalObjects en interne (ils sont donc maintenant dans MonkeyFishFactory au lieu de vrais globaux), il semble que le MonkeyFishFactory reste lui-même doit être un objet global pour pouvoir y accéder à tout moment si je veux créer un MonkeyFish .

Le motif Factory n’est-il pas la même chose que l’état global dans ce cas?

(Je suppose actuellement que l'état global est une mauvaise chose et que l'éliminer est une bonne chose.)

Était-ce utile?

La solution

Vous confondez les concepts ici?

Le modèle Factory est généralement appliqué lorsque vous renvoyez une instance d'une classe concrète qui se cache derrière une interface abstraite. L'idée est que l'appelant ne verra que l'interface et n'aura même pas à connaître le type concret de l'objet. Il s’agit de créer une instance d’objet basée sur des paramètres et de découpler la logique associée au choix de l’objet à créer de la part de l’utilisateur créant l’objet.

Ce que vous décrivez est un mélange de Singleton (ou MonoState) et de Factory. Votre usine est en état et ne peut donc pas être statique. Dans ce cas, vous devrez appliquer quelque chose comme le modèle Singleton pour contrôler la création d'une instance Factory unique avec les globales appropriées cachées à l'intérieur:

class IMonkeyFish {
public:
    virtual ~IMonkeyFish() = 0;
    virtual void go() = 0;
};

class Factory {
public:
    static Factory& instance();
    IMonkeyFish* createMonkeyFish();
protected:
    Factory(GlobalObjectA& a, GlobalObjectB& b, GlobalObjectC& c);
private:
    static Factory *theInstance;
    GlobalObjectA&  instanceOfA;
    GlobalObjectB&  instanceOfB;
    GlobalObjectC&  instanceOfC;
};

Factory& factory = Factory::instance();
IMonkeyFish* fishie = factory.createMonkeyFish();
fishie->go();

Le modèle Singleton régit la création de l'instance de fabrique. Le modèle Factory masque les détails entourant la création d'objets implémentant l'interface IMonkeyFish . The Good Thing (TM) cache l’état global et dissocie les détails concrets MonkeyFish de la création d’une instance.

L’utilisation ou la pertinence d’utiliser le Singleton est un tout autre problème. Il y a probablement beaucoup de discussions à ce sujet également.

Autres conseils

L'état global n'est pas une mauvaise chose en soi. L’état global public est une mauvaise chose. Le modèle Factory aide à encapsuler l’état global, ce qui est une bonne chose.

Il n'y a pas d'état global dans la fabrique. Il crée simplement des objets. Depuis pas n'importe quel état dans l'usine. C'est bien d'être global.

Vous n'avez pas à quitter les objets globaux. La fabrique de poisson Monkey devrait créer ces GlobalOjectA | B | C à la demande. Utilisez switch ou si méthode interne pour déterminer lequel.

Vous avez encapsulé le contrôle de la création d'objets dans une fabrique. Vous souhaitez que vos détails d'instanciation soient cachés et non reproduits partout où vous avez besoin d'un nouveau MonkeyFish. Pensez aux tests, à la responsabilité unique et à la loi de Demeter. Pourquoi votre classe qui souhaite utiliser un MonkeyFish devrait-elle savoir quoi que ce soit au sujet du travail nécessaire pour en construire un? Et si vous voulez tester MonkeyFish? Comment le ferais-tu si tu n'avais pas encapsulé les détails de la création?

Le travail d'une classe fabrique consiste à instancier un objet et à le renvoyer à l'appelant. ne pas choisir quel objet instancié global à utiliser. Votre exemple d’usine est donc incorrect. Ce devrait être:

int main()
{
  MonkeyFish * monkey_fish = MonkeyFishFactory::buildMonkeyFish("Bob");
  monkey_fish->go();
}

Avis, pas d'objets globaux, et MonkeyFishFactory n'est pas instancié.

Je pense que vous pensez au modèle Singleton, pas au modèle d'usine. Dans le modèle singleton, vous n’avez que l’instance d’une classe qui en fait l’équivalent d’un objet global, sauf qu’elle n’est pas associée à une variable globale.

Vous devez indiquer vos contraintes et vos exigences si vous souhaitez obtenir une bonne réponse. La chose la plus importante pour obtenir une bonne réponse est de savoir quelle question poser.

Dans les extraits de code que vous avez fournis, vous avez décidé d'utiliser des éléments globaux, mais cela n'a rien à voir avec l'utilisation ou non d'une fabrique. Si vous utilisez une fabrique qui dépend toujours de ces globaux, vous n’avez plus qu’une pièce de code à empiler avec le reste.

Essayez d’énoncer clairement ce que vous essayez d’atteindre et vous obtiendrez probablement une meilleure réponse.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top