2011-01-19 7 views
8

Przeczytałem artykuł Abstract Factory, Template Style autorstwa Jima Hyslopa i Herba Suttera. Ta fabryka jest zaimplementowana jako Singleton. Zapewniali łatwy sposób automatycznego rejestrowania klas za pomocą klasy pomocniczej RegisterInFactory.GenericFactory jako Singleton

Teraz czytałem kilka razy, że Singletons należy unikać, niektórzy nawet uważają je jako anty-wzory i że istnieją tylko kilka przypadków, w których są one przydatne. Czy to jeden z nich? Czy istnieje alternatywne podejście, które zapewnia tak łatwy sposób na autoregowanie klas?

+0

Jestem ciekaw, skąd ty patrz, że „Singletons należy unikać” ... – YeenFei

+0

„Singletons należy unikać” podobnie jak zmienne globalne. Abstract Factory to bardziej globalna usługa. Po inicjalizacji (rejestracji) wszyscy klienci czytają tylko z niego (poprosić o obiekty). Myślę, że Abstract Factory to jeden z przypadków, w których Singleton jest przydatny. – hansmaad

+0

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

Odpowiedz

2

Jak zawsze w przypadku tego rodzaju tematu, nie ma odpowiedzi, która odnosi się do każdego problemu. Niektórzy twierdzili, że należy unikać singletonu, gdy są wykorzystywane jako dostęp do usługi. Jest to użycie podobne do użycia zmiennych globalnych. W ten sposób można zamaskować fakt, że korzystać z usługi X w swojej realizacji:

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

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

możliwość utworzenia sprzężenia z MyWonderfulService że użytkownicy swojej klasie nie zgadnie. Ponadto, nie można łatwo sprawdzić swoją użyteczną klasę z udawanym usługi ...

Dlatego zazwyczaj wolą dependancy inversion:

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

    // [...] 
}; 

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

ten sposób jest zazwyczaj uważany lepiej jako sprzężenie pomiędzy klasa jest lżejszy. Niemniej jednak w przypadku niektórych usług, o których wiadomo, że mają szerokie zastosowanie w ramach, łatwiej jest użyć singletonu. Ma to sens w przypadku pojedynczej usługi, która jest usługą, która daje dostęp do wszystkich innych usług w ramach np.^^ Często jest używana do usług technicznych, takich jak na przykład logowanie.

my2c

Edit: Czytałem artykuł, ponieważ koncentruje się na AbstractFactories, użycie Singleton jest przypadkowy jeden, a nie decyzja projektowa. Jest to zrozumiałe w artykule, w którym nie chcesz pisać rzeczy, które nie doprowadzą cię do sedna.

+0

Aby mieć autorejestrowanie, jak pokazano w artykule, potrzebuję dostępu globalnego, ale nie potrzebuję go jako jedynej instancji. Alternatywą byłoby zatem dostarczenie go jako globalnego std :: cout, który pozwala mi go używać, ale w razie potrzeby nie uniemożliwi mi korzystania z drugiego. A może jest trzecia droga, może lepszy sposób na uzyskanie tej autorejestracji? – P3trus

+0

@ p3trus: Dodam konkretny przykład w mojej odpowiedzi, gdy mam czas ... Po prostu spróbuj na razie globalnie. Ja osobiście używam inwersji depandancji za każdym razem ... – neuro