Co jest złego w singletonach? [zamknięte]

Singleton pattern jest w pełni opłaconym członkiem GoF 'S pattern book , ale ostatnio wydaje się raczej osierocony przez świat deweloperów. Nadal używam sporo singletonów, szczególnie dla klas fabrycznych , i chociaż trzeba być trochę ostrożnym w kwestiach wielowątkowości( jak każda klasa), nie rozumiem, dlaczego są takie okropne.

Stack Overflow szczególnie wydaje się zakładać, że wszyscy zgadzają się, że Singletony są złe. Dlaczego?

W przypadku pytań prosimy o kontakt z działem obsługi klienta pod numerem telefonu: + 48 22 222 22 22, tel. + 48 22 222 22 22, fax + 48 22 222 22 22, fax + 48 22 222 22 22]}
Author: m87, 2008-09-26

30 answers

Parafrazowane z Brian Button:

  1. Są one zwykle używane jako instancja globalna, dlaczego to jest takie złe? Ponieważ ukrywasz zależności swojej aplikacji w kodzie, zamiast ujawniać je przez interfejsy. Tworzenie czegoś globalnego, aby uniknąć przekazywania tego jest zapachem kodu .

  2. Łamią zasadę jednej odpowiedzialności: z racji tego, że kontrolują własną twórczość i cykl życia.

  3. Z natury powodują, że kod jest ściśle sprzężony . To sprawia, że udawanie ich pod testem jest dość trudne w wielu przypadkach.

  4. Przenoszą stan przez cały okres użytkowania aplikacji. Kolejny hit do testów, ponieważ można skończyć z sytuacją, w której testy muszą być zamawiane, co jest dużym Nie Nie dla testów jednostkowych. Dlaczego? Ponieważ każdy test jednostkowy powinien być niezależny od drugiego.

 1162
Author: Jim Burger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-09 07:30:56

Singletony rozwiązują jeden (i tylko jeden) problem.

Contention Zasobów.

Jeśli masz jakiś zasób, który

(1) może mieć tylko jedną instancję i

(2) musisz zarządzać tą pojedynczą instancją,

Potrzebujesz singleton .

Nie ma zbyt wielu przykładów. Plik dziennika jest duży. Nie chcesz po prostu porzucić jednego pliku dziennika. Chcesz spłukać, zsynchronizować i prawidłowo zamknąć. Jest to przykład pojedynczy współdzielony zasób, którym należy zarządzać.

To rzadkość, że potrzebujesz Singletona. Powodem, dla którego są źli jest to, że czują się jak globalni i są w pełni opłaconym członkiem GoF wzorce projektowe książka.

Kiedy myślisz, że potrzebujesz globalnego, prawdopodobnie popełniasz straszny błąd projektowy.

 408
Author: S.Lott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-15 17:55:41

Niektórzy kodujący snobowie patrzą na nich z góry jak na gloryfikowanego globalnego. W ten sam sposób, w jaki wielu ludzi nienawidzi goto są inni, którzy nienawidzą idei używania globalnego . Widziałem, jak kilku programistów stara się unikać globalnego , ponieważ rozważali użycie jednego jako przyznanie się do porażki. Dziwne, ale prawdziwe.

W praktyce Wzór Singleton jest tylko techniką programowania, która jest przydatną częścią twojego zestaw pojęć. Od czasu do czasu może okazać się, że jest to idealne rozwiązanie i tak go używać. Ale używanie go tylko po to, aby móc pochwalić się używaniem wzorca projektowego jest tak samo głupie, jak odmowa użycia go, ponieważ jest to tylko global .

 311
Author: Phil Wright,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-15 00:22:16

Misko Hevery, z Google, ma kilka ciekawych artykułów na ten temat...

Singletony są patologicznymi kłamcami mA przykład testów jednostkowych, który ilustruje, w jaki sposób singletony mogą utrudnić zrozumienie łańcuchów zależności i uruchomienie lub przetestowanie aplikacji. Jest to dość skrajny przykład nadużycia, ale punkt, który czyni, jest nadal ważny:

Singletony to nic innego jak państwo globalne. Stan globalny sprawia, że Twoje obiekty mogą potajemnie uzyskać posiadanie rzeczy, które nie są zadeklarowane w ich API, a w rezultacie Singletony sprawiają, że Twoje API stają się patologicznymi kłamcami.

Where have all the Singletons Gone sprawia, że Wtrysk zależności ułatwił otrzymywanie instancji do konstruktorów, które ich wymagają, co łagodzi podstawową potrzebę złych, globalnych singletonów opisanych w pierwszym artykule.

 202
Author: jason,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-29 20:53:52

Myślę, że zamieszanie jest spowodowane faktem, że ludzie nie znają prawdziwego zastosowania wzoru Singletona. Nie mogę tego wystarczająco podkreślić. Singleton jest nie wzorem do owijania globali. Wzorzec Singletona powinien być użyty tylko do zagwarantowania, że jedna i tylko jedna instancja danej klasy istnieje w czasie wykonywania.

Ludzie myślą, że Singleton jest zły, ponieważ używają go dla globali. To z powodu tego zamieszania Singleton jest postrzegany z góry. Proszę., nie myl singletonów i globali. Jeśli zostanie użyty zgodnie z przeznaczeniem, do którego został przeznaczony, zyskasz ekstremalne korzyści z wzoru Singletona.

 104
Author: Cem Catikkas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-15 00:28:23

Jedną złą rzeczą w singletonach jest to, że nie można ich łatwo rozszerzyć. W zasadzie musisz zbudować jakiś wzór dekoratora lub coś takiego, jeśli chcesz zmienić ich zachowanie. Ponadto, jeśli pewnego dnia chcesz mieć wiele sposobów na zrobienie tej jednej rzeczy, zmiana może być dość bolesna, w zależności od sposobu ułożenia kodu.

Należy zauważyć, że jeśli używasz singletonów, spróbuj przekazać je temu, kto ich potrzebuje, a nie mieć do nich dostęp bezpośrednio... W przeciwnym razie, jeśli kiedykolwiek zdecydujesz się na wiele sposobów robienia tego, co robi singleton, będzie to raczej trudne do zmiany, ponieważ każda klasa osadza zależność, jeśli uzyskuje bezpośredni dostęp do Singletona.

Więc zasadniczo:

public MyConstructor(Singleton singleton) {
    this.singleton = singleton;
}

Zamiast:

public MyConstructor() {
    this.singleton = Singleton.getInstance();
}

Uważam, że ten rodzaj wzorca nazywa się dependency injection i jest ogólnie uważany za dobrą rzecz.

Jak każdy wzór... Zastanów się nad tym i zastanów się, czy jego użycie w danym sytuacja jest nieodpowiednia lub nie... Reguły są zazwyczaj łamane, a wzorce nie powinny być stosowane bez zastanowienia.
 71
Author: Mike Stone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-10 20:22:03

Wzór Singletona sam w sobie nie jest problemem. Problem polega na tym, że wzorzec jest często używany przez osoby rozwijające oprogramowanie z narzędziami obiektowymi, bez solidnego zrozumienia pojęć OO. Kiedy singletony są wprowadzane w tym kontekście, mają tendencję do przekształcania się w niewykonalne klasy, które zawierają metody pomocnicze do każdego małego użycia.

Singletony są również problemem z punktu widzenia testów. Mają tendencję do utrudniania pisania pojedynczych testów jednostkowych. Inwersja Kontrola (IoC) oraz dependency injection czy wzorce mają na celu przezwyciężenie tego problemu w sposób obiektowy, który nadaje się do testów jednostkowych.

W środowisku śmieci zebrane singletony mogą szybko stać się problemem w zakresie zarządzania pamięcią.

Istnieje również scenariusz wielowątkowy, w którym singletony mogą stać się wąskim gardłem, a także problemem synchronizacji.

 65
Author: Kimoz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-10 20:31:37

Singleton jest implementowany metodą statyczną. Metody statyczne są unikane przez ludzi, którzy przeprowadzają testy jednostkowe, ponieważ nie mogą być wyśmiewane lub stubowane. Większość ludzi na tej stronie jest wielkimi zwolennikami testów jednostkowych. Najbardziej powszechnie przyjętą konwencją, aby ich uniknąć, jest użycie wzoru inwersji sterowania .

 52
Author: Peter Mortensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-10 20:31:10

Singletony są również złe, jeśli chodzi o grupowanie . Ponieważ wtedy nie masz już "dokładnie jednego Singletona" w swojej aplikacji.

Rozważ następującą sytuację: jako programista musisz utworzyć aplikację internetową, która ma dostęp do bazy danych. Aby upewnić się, że współbieżne wywołania bazy danych nie kolidują ze sobą, tworzysz wątek-save SingletonDao:

public class SingletonDao {
    // songleton's static variable and getInstance() method etc. omitted
    public void writeXYZ(...){
        synchronized(...){
            // some database writing operations...
        }
    }
}

Więc jesteś pewien, że tylko jeden singleton w Twojej aplikacji istnieje i cała baza danych przechodzi przez to jeden i jedyny SingletonDao. Twoje środowisko produkcyjne wygląda teraz tak: Single Singleton

Jak na razie wszystko w porządku.

Zastanów się, czy chcesz skonfigurować wiele instancji aplikacji internetowej w klastrze. Nagle masz coś takiego:

Wiele singletonów

To brzmi dziwnie, ale teraz masz wiele singletonów w aplikacji . I to jest dokładnie to, czego singleton nie powinien być: posiadanie wielu przedmiotów. Jest to szczególnie złe, jeśli, Jak pokazano w tym przykładzie chcesz wykonywać zsynchronizowane połączenia do bazy danych. Oczywiście jest to przykład złego użycia singletonu. Ale przesłanie tego przykładu brzmi: nie możesz polegać na tym, że w Twojej aplikacji jest dokładnie jedna instancja Singletona-zwłaszcza jeśli chodzi o klastrowanie.
 42
Author: Uooo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-22 14:34:10
  1. jest łatwo (ab)używana jako zmienna globalna.
  2. Klasy, które zależą od singletonów, są stosunkowo trudniejsze do przetestowania w izolacji.
 34
Author: jop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-14 21:26:15

Monopol jest diabłem, a singletony ze stanem nieprzeczytanym/zmiennym są "prawdziwym" problemem...

Po przeczytaniu Singletony są patologicznymi kłamcami jak sugerowano w odpowiedzi Jasona natknąłem się na tę małą ciekawostkę, która dostarcza najlepiej zaprezentowanego przykładu Jak singletony są często nadużywane.

Global jest złe, ponieważ:

  • a. powoduje konflikt przestrzeni nazw
  • b. eksponuje Państwo w nieuzasadnionym Moda

Jeśli chodzi o Singletony

    A. jawny sposób ich wywołania zapobiega konfliktom, więc punkt a. nie jest problemem
  • b. Singletony bez stanu są (jak fabryki) nie stanowią problemu. Singletony ze stanem mogą ponownie należeć do dwóch kategorii, tych, które są niezmienne lub zapisują raz i odczytują wiele (pliki config/property). Nie są złe. Mutable Singletons, które są swego rodzaju posiadaczami odniesienia są te, które mówisz z.

W ostatniej wypowiedzi odnosi się do koncepcji bloga "singletons are liars".

Jak to ma zastosowanie do monopolu?

Aby rozpocząć grę w monopoly, najpierw:

  • najpierw ustalamy zasady, aby wszyscy byli na tej samej stronie
  • każdy ma równy start na początku gry
  • tylko jeden zestaw reguł jest przedstawiony, aby uniknąć nieporozumień
  • zasady nie mogą się zmieniać w ciągu gra

Teraz, dla każdego, kto nie Naprawdę grał w monopoly, te standardy są idealne w najlepszym razie. Porażka w monopoly jest trudne do przełknięcia, ponieważ, monopoly jest o pieniądze, jeśli przegrasz trzeba żmudnie oglądać resztę graczy zakończyć grę, a straty są zwykle szybkie i miażdżące. Tak więc zasady zwykle się przekręcają w pewnym momencie, aby służyć własnym interesom niektórych graczy kosztem innych.

Więc grasz w monopoly z przyjaciele: Bob, Joe i Ed. Szybko budujesz swoje imperium i zużywasz udział w rynku w wykładniczym tempie. Twoi przeciwnicy słabną i zaczynasz czuć krew (w przenośni). Twój kumpel Bob włożył wszystkie swoje pieniądze w zablokowanie jak największej liczby niskiej wartości nieruchomości, ale jego nie otrzymuje wysokiego zwrotu z inwestycji, tak jak oczekiwał. Bob, jako udar pecha, ląduje na Promenadzie i jest usuwany z gry.

Teraz gra przechodzi z przyjaznego rzucania kośćmi do poważna sprawa. Bob jest przykładem porażki, a Joe i Ed nie chcą skończyć jak "ten facet". Tak więc, będąc wiodącym graczem, nagle, stać się wrogiem. Joe i Ed zaczynają ćwiczyć transakcje pod stołem, zastrzyki pieniędzy za plecami, niedocenianą wymianę domów i ogólnie wszystko, co osłabi Cię jako gracza, dopóki jeden z nich nie wzrośnie na szczyt.

Wtedy, zamiast jednego z nich wygrywającego, proces zaczyna się od nowa. Nagle skończony zbiór zasad staje się ruchomym celem, a gra przekształca się w rodzaj interakcji społecznych, które stanowią podstawę każdego wysoko ocenianego reality show od czasu "ryzykantów". Dlaczego, ponieważ Zasady się zmieniają i nie ma konsensusu co do tego, jak / dlaczego/co mają reprezentować, a co ważniejsze, nikt nie podejmuje decyzji. Każdy gracz w grze, W tym momencie, ustala swoje własne zasady i chaos następuje, aż dwóch graczy są zbyt zmęczeni, aby utrzymać szaradę i powoli się poddaj.

Tak więc, gdyby regulamin Gry dokładnie reprezentował singleton, Regulamin monopoly byłby przykładem nadużycia.

Jak to ma zastosowanie do programowania?

Pomijając wszystkie oczywiste problemy związane z bezpieczeństwem i synchronizacją wątków, które występują w mutable singletons... Jeśli masz jeden zestaw danych, który może być odczytywany/manipulowany przez wiele różnych źródeł jednocześnie i istnieje w trakcie życia wykonywania aplikacji, to prawdopodobnie dobry czas, aby cofnąć się i zapytać "czy używam odpowiedniego typu struktury danych tutaj".

Osobiście widziałem, jak programista nadużywa Singletona, używając go jako jakiegoś pokręconego magazynu baz danych w aplikacji. Po bezpośredniej pracy nad kodem, mogę zaświadczyć, że był powolny (ze względu na wszystkie blokady wątku potrzebne, aby uczynić go bezpiecznym dla wątku) i koszmar do pracy (ze względu na nieprzewidywalny / przerywany charakter błędów synchronizacji), i prawie niemożliwe do przetestowania w warunkach "produkcyjnych". Oczywiście, system mógł zostać opracowany przy użyciu polling / signaling, aby przezwyciężyć niektóre problemy z wydajnością, ale to nie rozwiązałoby problemów z testowaniem i po co się martwić, gdy "prawdziwa" baza danych może już osiągnąć tę samą funkcjonalność w znacznie bardziej solidny / skalowalny sposób.

Singleton jest tylko opcją, jeśli potrzebujesz tego, co zapewnia singleton. Instancja obiektu tylko do odczytu. Ta sama zasada powinna kaskada do Właściwości obiektu / członków, jak również.

 30
Author: Evan Plaice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:27

Singleton nie chodzi o pojedynczą instancję!

W przeciwieństwie do innych odpowiedzi, nie chcę mówić o tym, co jest nie tak z Singletonami, ale pokazać, jak potężne i niesamowite są, gdy są używane poprawnie!

  • Problem : Singleton może być wyzwaniem w środowisku wielowątkowym
    rozwiązanie : użyj procesu bootstrap z pojedynczym wątkiem, aby zainicjować wszystkie zależności Singletona.
  • Problem: trudno wyśmiewać singletony.
    rozwiązanie : użyj metody Factory wzorzec do szydzenia
    MyModel myModel = Factory.inject(MyModel.class); Możesz zmapować MyModel do TestMyModel klasy, która ją dziedziczy, wszędzie po wstrzyknięciu MyModel otrzymasz TestMyModel instread.
  • Problem : Singletony mogą powodować pory pamięci, ponieważ nigdy nie są usuwane.
    rozwiązanie: cóż, pozbądź się ich! Zaimplementuj callback w swojej aplikacji, aby prawidłowo pozbyć się singletonów, należy usunąć wszelkie dane z nimi związane i wreszcie: usunąć je z Fabryka.

Jak powiedziałem w tytule singleton nie są o pojedynczej instancji.

  • Singletons poprawia czytelność : możesz spojrzeć na swoją klasę i zobaczyć, jaki singleton wstrzyknął, aby dowiedzieć się, jakie są jego zależności.
  • Singletons ulepsza konserwację: Po usunięciu zależności z klasy, którą właśnie usunąłeś singleton injection, nie musisz edytować dużego linku innych klas, które właśnie przeniosły Twoją zależność around (This is smelly code for me @Jim Burger)
  • Singletons poprawia pamięć i wydajność: gdy w Twojej aplikacji dzieje się coś, co wymaga długiego łańcucha wywołań zwrotnych, marnujesz pamięć i wydajność, używając Singletona wycinasz środkowego człowieka i poprawiasz wydajność i zużycie pamięci(unikając niepotrzebnych przydziałów zmiennych lokalnych).
 22
Author: Ilya_Gazman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:07

Moja odpowiedź na to, jak Singletony są złe, zawsze brzmi: "trudno jest zrobić dobrze". Wiele podstawowych komponentów języków to singletony (klasy, funkcje, przestrzenie nazw, a nawet operatory), podobnie jak komponenty w innych aspektach obliczeń (localhost, domyślna trasa, wirtualny system plików, itp.), i to nie przez przypadek. Chociaż powodują kłopoty i frustrację od czasu do czasu, mogą również sprawić, że wiele rzeczy działa o wiele lepiej.

Dwie największe wpadki jakie widzę to: traktując to jak globalne i nie definiując zamknięcia Singletonu.

Wszyscy mówią o Singletonie jako o globalach, ponieważ w zasadzie są. Jednak wiele (niestety, nie wszystkie) zła w globalnym nie pochodzi z natury rzeczy z bycia globalnym, ale z tego, jak go używasz. To samo dotyczy singletonów. Bardziej, że "pojedyncza instancja" nie musi oznaczać "globalnie dostępna". Jest to bardziej naturalny produkt uboczny, a biorąc pod uwagę całe zło, które wiemy, że pochodzi z niego, nie powinniśmy być w takim pospiesz się, aby wykorzystać globalną dostępność. Gdy programiści zobaczą Singleton, zdają się zawsze uzyskiwać do niego dostęp bezpośrednio poprzez jego metodę instancji. Zamiast tego powinieneś nawigować do niego tak, jak każdy inny obiekt. Większość kodu nie powinna być nawet świadoma, że ma do czynienia z Singletonem (luźne sprzężenie, prawda?). Jeśli tylko mały fragment kodu uzyska dostęp do obiektu tak, jakby był globalny, wiele szkód zostanie cofniętych. Zalecam wymuszenie tego poprzez ograniczenie dostępu do funkcji instancji.

Singleton kontekst jest również bardzo ważny. Cechą charakterystyczną Singletonu jest to, że istnieje "tylko jeden", ale prawda jest taka, że jest to "tylko jeden" w jakimś kontekście/przestrzeni nazw. Zazwyczaj są one jednym z: jeden na wątek, proces, adres IP lub klaster, ale może być również jeden na procesor, maszynę, przestrzeń nazw języka / Klasa loader / cokolwiek, podsieć, Internet, itp.

Innym, mniej powszechnym błędem jest ignorowanie stylu życia singletonów. To, że jest tylko jeden, nie znaczy, że Singleton czy jakiś wszechmocny "zawsze był i zawsze będzie", nie jest też ogólnie pożądany (obiekty bez początku i końca łamią wszelkiego rodzaju użyteczne założenia w kodzie i powinny być stosowane tylko w najbardziej rozpaczliwych okolicznościach.

Jeśli unikniesz tych błędów, Singletons nadal może być PITA, bit jest gotowy, aby zobaczyć wiele najgorszych problemów są znacznie złagodzone. Wyobraź sobie Singleton Javy, który jest jawnie zdefiniowany jako raz na classloader (co oznacza, że potrzebuje bezpieczeństwa wątku Polityka), ze zdefiniowanymi metodami tworzenia i niszczenia oraz cyklem życia, który dyktuje, kiedy i w jaki sposób są wywoływane, i czyja metoda "instancja" ma ochronę pakietu, więc jest ogólnie dostępna za pośrednictwem innych, nie-globalnych obiektów. Nadal potencjalne źródło kłopotów, ale na pewno znacznie mniej kłopotów.

Niestety, zamiast uczyć dobrych przykładów jak robić Singletony. Uczymy złych przykładów, pozwalamy programistom uciec z nich przez jakiś czas, a następnie mówimy im, że są złym projektem wzór.

 20
Author: Christopher Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-10 20:42:38

Zobacz Wikipedię Singleton_pattern

Jest również uważany za anty-wzorzec przez niektórych ludzi, którzy uważają, że jest zbyt używany, wprowadzając niepotrzebne ograniczenia w sytuacjach, w których jedyna instancja klasy nie jest w rzeczywistości wymagana.[1][2][3][4]

Odniesienia (tylko odpowiednie odniesienia z Artykułu)

  1. ^ Alex Miller. Patterns I hate # 1: Singleton, lipiec 2007
  2. ^ Scott Densmore. dlaczego singletony są evil , Maj 2004
  3. ^ Steve Yegge. Singletons considered stupid , September 2004
  4. ^ J. B. Rainsberger, IBM. mądrze używaj singletonów , lipiec 2001
 20
Author: GUI Junkie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-08 09:19:24

Nie chodzi o to, że same singletony są złe, ale wzór konstrukcyjny GoF jest. Jedynym słusznym argumentem jest to, że wzorzec projektowy GoF nie nadaje się do testowania, zwłaszcza jeśli testy są prowadzone równolegle.

Użycie pojedynczej instancji klasy jest poprawnym konstruktem, o ile zastosujesz następujące środki w kodzie:

  1. Upewnij się, że klasa, która będzie używana jako singleton, implementuje interfejs. Umożliwia to implementację stubów lub moków korzystanie z tego samego interfejsu

  2. Upewnij się, że Singleton jest bezpieczny dla nici. To pewne.

  3. Singleton powinien być prosty i nie zbyt skomplikowany.

  4. Podczas wykonywania aplikacji, w której singletony muszą być przekazywane do danego obiektu, Użyj klasy factory, która buduje ten obiekt i niech Klasa factory przekaże instancję Singletona do potrzebującej jej klasy.

  5. Podczas badania oraz w celu zapewnienia deterministycznego zachowanie, Utwórz klasę singleton jako osobną instancję jako samą klasę lub stub / mock, który implementuje jej zachowanie i przekaż ją tak, jak jest do klasy, która tego wymaga. Nie używaj czynnika klasy, który tworzy obiekt testowany, który potrzebuje Singletona podczas testu, ponieważ przejdzie on pojedynczą globalną instancję tego obiektu, która pokonuje ten cel.

W naszych rozwiązaniach z dużym powodzeniem wykorzystaliśmy Singletony, które można przetestować, zapewniając deterministyczne zachowanie w równoległych strumieniach testowych.

 16
Author: 2 revs, 2 users 92%user1578119,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-12 16:48:35

Vince Huston ma te kryteria, które wydają mi się rozsądne:

Singleton należy rozważyć tylko wtedy, gdy wszystkie trzy z następujących kryteriów są spełnione:

  • własność pojedynczej instancji nie może być w rozsądny sposób przypisana
  • leniwa inicjalizacja jest pożądana
  • globalny dostęp nie jest przewidziany dla

Jeśli własność pojedynczej instancji, kiedy i jak następuje inicjalizacja i globalny dostęp nie są kwestie, Singleton nie jest wystarczająco interesujące.

 15
Author: js.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-23 09:58:11

Chciałbym odnieść się do 4 punktów w zaakceptowanej odpowiedzi, mam nadzieję, że ktoś wyjaśni, dlaczego się mylę.

  1. Dlaczego ukrywanie zależności w kodzie jest złe? Istnieją już dziesiątki ukrytych zależności (wywołania C runtime, wywołania API OS, wywołania funkcji globalnych), a zależności Singletona są łatwe do znalezienia (np. search ()).

    "tworzenie czegoś globalnego, aby uniknąć przekazywania tego, to zapach kodu."Dlaczego nie jest przekazywanie czegoś wokół, aby uniknąć czyniąc go singleton zapach kodu?

    Jeśli przekazujesz obiekt przez 10 funkcji w stosie wywołań tylko po to, aby uniknąć Singletona, czy to takie wspaniałe?

  2. Zasada jednej odpowiedzialności: myślę, że jest to nieco niejasne i zależy od twojej definicji odpowiedzialności. Istotne pytanie brzmiałoby: dlaczego dodanie tego specyficznego "odpowiedzialności" do sprawy klasowej?

  3. Dlaczego przekazywanie obiektu do klasy powoduje, że jest on bardziej zwarty niż używanie tego obiektu jako singleton z klasy?

  4. Dlaczego zmienia się to, jak długo trwa Państwo? Singletony mogą być tworzone lub niszczone ręcznie, więc kontrola nadal tam jest, i można uczynić życie takim samym, jak życie obiektu innego niż singleton.

W odniesieniu do testów jednostkowych:

  • nie wszystkie klasy muszą być jednostkowe tested
  • nie wszystkie klasy, które muszą być jednostkowe testowana potrzeba zmiany implementacja singletonu
  • Jeśli Czy muszą być badane jednostkowo i czy trzeba zmienić realizację, łatwo zmienić klasę z korzystanie z singletonu do posiadania singleton przeszedł do niej przez zależność wstrzyknięcie.
 14
Author: Jon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-07 13:31:48

Nie będę komentował argumentów dobra/zła, ale nie używałem ich od czasu Wiosny. Użycie dependency injection praktycznie usunęło moje wymagania dotyczące singletonów, servicelocators i fabryk. Uważam to za dużo bardziej produktywne i czyste środowisko, przynajmniej dla rodzaju pracy, którą wykonuję (aplikacje internetowe oparte na Javie).

 13
Author: Peter Mortensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-10 20:37:38

Singletony są złe z purystycznego punktu widzenia.

Z praktycznego punktu widzenia, singleton jest kompromisem pomiędzy rozwojem czasu a złożonością .

Jeśli wiesz, że Twoja aplikacja nie zmieni się tak bardzo, są całkiem w porządku. Wiedz tylko, że być może będziesz musiał zmienić ustawienia, jeśli twoje wymagania zmienią się w nieoczekiwany sposób(co w większości przypadków jest całkiem OK).

Singletony czasami komplikują również testy jednostkowe.

 12
Author: tacone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-10 20:40:06

Nie ma nic z natury złego w wzorze, zakładając, że jest on używany do jakiegoś aspektu twojego modelu, który jest naprawdę pojedynczy.

Uważam, że luz wynika z jego nadużywania, co z kolei wynika z faktu, że jest to najprostszy wzorzec do zrozumienia i wdrożenia.

 11
Author: Ben Hoffstein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 06:07:41

Singleton jest wzorem i może być używany lub nadużywany, tak jak każde inne narzędzie.

Złą częścią Singletona jest zazwyczaj użytkownik(lub powinienem powiedzieć niewłaściwe użycie Singletona do rzeczy, do których nie jest przeznaczony). Największym przestępcą jest użycie Singletona jako fałszywej zmiennej globalnej.

 11
Author: Loki Astari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-10 20:40:59

Kiedy piszesz kod używając singletonów, powiedzmy, loggera lub połączenia z bazą danych, a potem odkrywasz, że potrzebujesz więcej niż jednego dziennika lub więcej niż jednej bazy danych, jesteś w tarapatach.

Singletony bardzo utrudniają przejście od nich do zwykłych obiektów.

Poza tym, zbyt łatwo jest napisać singleton bez wątku.

Zamiast używać singletonów, powinieneś przekazać wszystkie potrzebne obiekty użytkowe z funkcji do funkcji. Można to uprościć, jeśli owiniesz je wszystkie w obiekt pomocniczy, jak to:

void some_class::some_function(parameters, service_provider& srv)
{
    srv.get<error_logger>().log("Hi there!");
    this->another_function(some_other_parameters, srv);
}
 8
Author: Roman Odaisky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 06:20:10

Problemy z singletonami to kwestia zwiększonego zasięgu, a zatem sprzężenia . Nie można zaprzeczyć, że istnieją sytuacje, w których potrzebujesz dostępu do pojedynczej instancji i można to osiągnąć w inny sposób.

Teraz wolę zaprojektować wokół inwersję kontenera kontrolnego (IoC) I pozwolić na kontrolowanie życia przez kontener. Daje to korzyści klasom, które zależą od instancji, aby być nieświadomym faktu, że jest jeden przypadek. Żywotność Singletona można zmienić w przyszłości. Kiedyś taki przykład napotkałem niedawno było łatwe dostosowanie z pojedynczego gwintowane do wielowątkowych.

FWIW, jeśli to PIA przy próbie jednostkowej to będzie Pia przy próbie debugowania, naprawy błędów lub ulepszenia.

 7
Author: Mark Lindell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-10 20:53:40

Ostatni artykuł na ten temat autorstwa Chrisa Reath w kodowanie bez Komentarzy.

Uwaga: kodowanie bez komentarzy nie jest już ważne. Jednak linkowany artykuł został sklonowany przez innego użytkownika.

Http://geekswithblogs.net/AngelEyes/archive/2013/09/08/singleton-i-love-you-but-youre-bringing-me-down-re-uploaded.aspx

 7
Author: stephenbayer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-30 18:43:46

Oto jeszcze jedna rzecz o singletonach, której jeszcze nikt nie powiedział.

W większości przypadków "singletonity" jest szczegółem implementacji dla jakiejś klasy, a nie charakterystycznym dla jej interfejsu. Odwrócenie kontenera kontrolnego może ukryć tę cechę przed użytkownikami klasy; wystarczy zaznaczyć klasę jako singleton (z @Singleton adnotacją na przykład w Javie) i tyle; IoCC zrobi resztę. Nie musisz zapewniać globalnego dostępu do wystąpienia singleton, ponieważ dostęp jest już zarządzane przez IoCC. W związku z tym nie ma nic złego w Singletonach MKOl.

Gof Singletons w przeciwieństwie do IoC Singletons mają ujawniać "singletonity" w interfejsie za pomocą metody getInstance() i tak, że cierpią z powodu wszystkiego, co zostało powiedziane powyżej.

 6
Author: Volodymyr Frolov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-01 21:29:40

Singletony nie są złe. Jest źle tylko wtedy, gdy robisz coś wyjątkowego na całym świecie, co nie jest wyjątkowe na całym świecie.

Istnieją jednak "usługi zakresu aplikacji" (pomyśl o systemie komunikacyjnym, który sprawia, że komponenty wchodzą w interakcję) - to wywołuje singleton, klasę "MessageQueue", która ma metodę " SendMessage(...)".

Możesz wykonać następujące czynności z całego miejsca:

MessageQueue.Aktualne.SendMessage (new MailArrivedMessage (...));

I oczywiście, do:

MessageQueue.Aktualne.RegisterReceiver (this);

W klasach implementujących IMessageReceiver.

 6
Author: StormianRootSolver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-05 10:42:47

Zbyt wiele osób umieszcza w singletonie obiekty, które nie są bezpieczne dla wątków. Widziałem przykłady DataContext (LINQ do SQL) wykonanego we wzorze singleton, pomimo faktu, że DataContext nie jest bezpieczny dla wątków i jest czysto obiektem typu unit-of-work.

 6
Author: Peter Mortensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-10 20:44:42

Ponieważ są one w zasadzie obiektowymi zmiennymi globalnymi, zazwyczaj możesz zaprojektować swoje klasy w taki sposób, aby nie były potrzebne.

 4
Author: Ycros,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 06:05:36

Wzorzec pojawia się, gdy kilka osób (lub zespołów) dociera do podobnych lub identycznych rozwiązań. Wiele osób nadal używa singletonów w swojej oryginalnej formie lub używa szablonów fabrycznych(dobra dyskusja w nowoczesnym C++). Współbieżność i trudności w zarządzaniu żywotnością obiektu są głównymi przeszkodami, z tymi pierwszymi łatwo zarządzanymi, jak sugerujesz.

Jak wszystkie wybory, Singleton ma swój udział wzlotów i upadków. Myślę, że można je stosować z umiarem, szczególnie w przypadku obiektów, które przetrwają żywotność aplikacji. Fakt, że przypominają (i prawdopodobnie są) globalami, prawdopodobnie zapoczątkował purystów.

 4
Author: user22044,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 06:14:25

Po pierwsze klasa i jej współpracownicy powinni najpierw wykonać swój zamierzony cel, a nie skupiać się na deoendentach. Zarządzanie cyklem życia (gdy instancje są kreowane snd, gdy wychodzą z zakresu) nie powinno być częścią odpowiedzialności cladses. Akceptowaną najlepszą praktyką jest tworzenie lub konfigurowanie nowego komponentu do zarządzania zależnościami za pomocą iniekcji zależności.

Często oprogramowanie staje się bardziej skomplikowane ma sens posiadanie wielu niezależnych instancji Klasa "singleton" z innym stanem. Popełnianie kodu, aby po prostu złapać singleton, jest błędne w takich przypadkach. Używam Singletona.getInstance () może być ok dla małych prostych systemów, ale nie działa / nie skaluje się, gdy ktoś może potrzebować innej instancji tej samej klasy.

Żadna klasa nie powinna być traktowana jako singleton, ale raczej powinno to być zastosowanie jej użycia lub sposobu, w jaki jest używana do konfigurowania zależności. Dla szybkiego i nieprzyjemnego to nie ma znaczenia - po prostu luke hardcoding powiedzieć ścieżki plików nie ma to znaczenia, ale w przypadku większych aplikacji takie zależności muszą być uwzględniane i zarządzane w bardziej odpowiedni sposób za pomocą DI.

Problemy, które singleton powoduje w testach, są objawem ich twardo zakodowanego pojedynczego przypadku użycia / środowiska. Zestaw testów i wiele testów są poszczególne i oddzielne coś, co nie jest zgodne z hardcoding singleton.

 4
Author: mP.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-28 01:14:39