Domanda

Diciamo che ho una lezione come questa:

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

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

Senza una fabbrica, devo fare quanto segue per creare un'istanza di un MonkeyFish .

GlobalObjectA a;
GlobalObjectB b;
GlobalObjectC c;

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

D'altra parte, se ho un MonkeyFishFactory , sembra che debba farlo:

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. Ho ancora oggetti globali.

  2. Anche se MonkeyFishFactory stesso ha creato internamente il GlobalObjects (quindi ora si trovano all'interno di MonkeyFishFactory invece dei veri globi), sembra che MonkeyFishFactory stesso sia ancora deve essere un oggetto globale in modo che io possa accedervi ogni volta che voglio creare un MonkeyFish.

In questo caso il modello Factory non è la stessa cosa dello stato globale?

(Attualmente sto operando partendo dal presupposto che lo stato globale è una cosa negativa, e eliminarla è una cosa positiva.)

È stato utile?

Soluzione

Stai confondendo concetti qui?

Il modello Factory viene solitamente applicato quando si restituisce un'istanza di una classe concreta che si nasconde dietro un'interfaccia astratta. L'idea è che il chiamante vedrà solo l'interfaccia e non dovrà nemmeno sapere quale sia il tipo concreto dell'oggetto. Si tratta solo di creare un'istanza di oggetto basata su parametri e di disaccoppiare la logica associata alla decisione di quale oggetto creare dall'utente che crea l'oggetto.

Quello che stai descrivendo è una miscela di Singleton (o MonoState) e Factory. La tua fabbrica ha stato quindi non può essere resa statica. In questo caso, dovrai applicare qualcosa come il modello Singleton per controllare la creazione di una singola istanza Factory con i globi appropriati nascosti al suo interno:

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

Il modello Singleton regola la creazione dell'istanza di fabbrica. Il modello Factory nasconde i dettagli che circondano la creazione di oggetti che implementano l'interfaccia IMonkeyFish . The Good Thing (TM) è il nascondimento dello stato globale e il disaccoppiamento dei dettagli concreti MonkeyFish dalla creazione di un'istanza.

L'uso o la correttezza dell'uso del Singleton è comunque un altro problema. Probabilmente ci sono anche un sacco di fili che fluttuano attorno a questo.

Altri suggerimenti

Lo stato globale non è di per sé una cosa negativa. Lo stato globale pubblico è una cosa negativa. Il modello Factory aiuta a incapsulare lo stato globale, che è una buona cosa.

Non ci sono stati globali in fabbrica. Crea solo oggetti. Dal momento che non qualsiasi stato in fabbrica. Va bene essere globali.

Non devi lasciare oggetti globali. La fabbrica di pesci scimmia dovrebbe creare tali GlobalOjectA | B | C su richiesta. Utilizzando il metodo switch o if inside per determinare quale.

Hai il controllo incapsulato sulla creazione di oggetti in una fabbrica. Vuoi che i dettagli della tua istanza siano nascosti, non riprodotti ovunque tu abbia bisogno di un nuovo MonkeyFish. Pensa ai test, alla singola responsabilità e alla legge di Demetra. Perché la tua classe che vuole usare un MonkeyFish dovrebbe sapere qualcosa sul lavoro necessario per costruirne uno. Cosa succede se si desidera testare MonkeyFish? Come lo faresti se non avessi incapsulato i dettagli della creazione?

Il compito di una classe factory è di creare un'istanza di un oggetto e passarlo al chiamante; non scegliere quale oggetto istanziato globale usare. Quindi, l'esempio di fabbrica non è corretto. Dovrebbe essere:

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

Nota, nessun oggetto globale e MonkeyFishFactory non è istanziato.

Penso che tu stia pensando al Singleton Pattern, non al Factory Pattern. Nel modello singleton hai solo l'istanza di una classe che sostanzialmente lo rende l'equivalente di un oggetto globale, tranne per il fatto che non vi è alcuna variabile globale ad esso collegata.

Dovresti indicare i tuoi vincoli e requisiti se vuoi ottenere una buona risposta. La cosa più importante per ottenere una buona risposta è sapere quale domanda porre.

Negli snippet di codice forniti hai deciso di utilizzare i globali, ma ciò non ha nulla a che fare con l'utilizzo di Factory o meno. Se usi una fabbrica che dipende ancora da quei globi, allora hai solo un altro pezzo di codice da accumulare con il resto.

Prova a dichiarare chiaramente cosa stai cercando di ottenere e probabilmente otterrai una risposta migliore.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top