2011-01-19 14 views
8

Ho letto l'articolo Abstract Factory, Template Style di Jim Hyslop e Herb Sutter. Questo stabilimento è implementato come Singleton. Hanno fornito un modo semplice per registrare automaticamente le classi con la classe helper RegisterInFactory.GenericFactory as Singleton

Ora ho letto più volte che Singletons dovrebbe essere evitato, alcuni addirittura li considerano come anti-pattern e che ci sono solo alcuni casi in cui sono utili. È uno di questi? O c'è un approccio alternativo che fornisce un modo così semplice per le classi di autoregistrazione?

+0

Sono curioso di sapere da dove si riferisce che "I gemelli dovrebbero essere evitati" ... – YeenFei

+0

"I gemelli dovrebbero essere evitati" proprio come le variabili globali. Una fabbrica astratta è più simile a un servizio globale. Dopo l'inizializzazione (Registrazione) tutti i client leggono solo da esso (chiedi oggetti). Penso che Abstract Factory sia uno dei casi in cui un Singleton è utile. – hansmaad

+0

ovvero http://stackoverflow.com/questions/86582/singleton-how-should-it-be-used o http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827. aspx – P3trus

risposta

2

Come sempre per questo tipo di argomento, non esiste una risposta valida per tutti i problemi. Alcuni hanno affermato che il singleton dovrebbe essere evitato quando viene utilizzato come accesso a un servizio. È un uso simile all'utilizzo di variabili globali. In questo modo si mascherare il fatto che si utilizza il servizio X nell'implementazione:

// in header 
class MyUsefulClass 
{ 
    public: 
    void doSomethingUseful(); 
}; 

// in .cpp 
MyUsefulClass::doSomethingUseful() 
{ 
    // ... 
    MyWonderfulService::instance().doService1(); 
    // ... 
    MyWonderfulService::instance().doService2(); 
} 

Si crea un accoppiamento con MyWonderfulService che gli utenti della vostra classe non possono immaginare. Inoltre, non si può facilmente verificare la classe utile, con un servizio di finto ...

Ecco perché io di solito preferisco dependancy inversion:

// in header 
class MyUsefulClass 
{ 
    public: 
    void setServiceToUse(MyService&); 
    void doSomethingUseful(); 

    // [...] 
}; 

// in .cpp 
MyUsefulClass::doSomethingUseful() 
{ 
    // ... 
    _myService->doService1(); 
    // ... 
    _myService->doService2(); 
} 

In questo modo è di solito considerato meglio come l'accoppiamento tra classe è più leggero. Tuttavia, per alcuni servizi, che sono ben noti essere di uso diffuso in un framework, è più semplice utilizzare un singleton. Ha senso per un singolo servizio che è il servizio che ti dà accesso a tutti gli altri servizi in un framework, ad esempio ^^ È spesso utilizzato per servizi tecnici come la registrazione, per esempio.

MY2C

Edit: Ho letto l'articolo, come il focus è sul AbstractFactories, l'uso di un Singleton è casuale, non è una decisione di progettazione. È comprensibile in un articolo in cui non vuoi scrivere cose che non ti portano al punto.

+0

Quindi per avere l'autoregistrazione come mostrato nell'articolo ho bisogno dell'accesso globale ma non ho bisogno che sia l'unica istanza. Un'alternativa sarebbe quindi quella di fornirlo come globale come std :: cout che mi consente di usarlo, ma non mi impedisce di usarne un secondo se necessario. O c'è una terza via, forse un modo migliore per raggiungere questa autoregistrazione? – P3trus

+0

@ p3trus: aggiungerò un esempio concreto nella mia risposta quando avrò tempo ... Prova un globale per ora. Io uso sempre l'inversione di depandance ogni volta ... – neuro