Na temat wzorców projektowych: Kiedy powinienem używać Singletona? [zamknięte]

Gloryfikowana zmienna globalna-staje się gloryfikowaną klasą globalną. Niektórzy mówią, że łamanie projektowania zorientowanego obiektowo.

Daj mi scenariusze, inne niż stary dobry logger, gdzie ma sens używać Singletona.

Author: Peter Mortensen, 2008-10-23

18 answers

W poszukiwaniu prawdy odkryłem, że istnieje naprawdę niewiele "akceptowalnych" powodów, aby używać Singletona.

Jednym z powodów, które często pojawiają się w Internecie, jest klasa "logowania" (o której wspomniałeś). W tym przypadku, Singleton może być użyty zamiast pojedynczej instancji klasy, ponieważ Klasa logowania zwykle musi być używana w kółko ad nauseam przez każdą klasę w projekcie. Jeśli każda klasa używa tej klasy logowania, zależność zastrzyk staje się uciążliwy.

Logowanie jest specyficznym przykładem" akceptowalnego " Singletona, ponieważ nie wpływa na wykonanie kodu. Wyłącz logowanie, wykonanie kodu pozostaje takie samo. Włącz to, tak samo. Misko umieszcza to w następujący sposób w głównej przyczynie singletonów: "informacja tutaj płynie w jeden sposób: z Twojej aplikacji do REJESTRATORA. Mimo że rejestratory są stanem globalnym, ponieważ żadne informacje nie są przesyłane z rejestratorów do Twojej aplikacji, Rejestratory są akceptowalne."

Jestem pewien, że są też inne ważne powody. Alex Miller, w "Patterns I Hate", mówi o lokalizatorach usług i interfejsie użytkownika po stronie klienta, które są prawdopodobnie" akceptowalnymi " wyborami.

Czytaj więcej na Singleton I love you, but you ' re bringing me down.

 314
Author: CodingWithoutComments,
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-02-03 18:58:43

Kandydat Singleton musi spełniać trzy wymagania:

  • kontroluje współbieżny dostęp do współdzielonego zasobu.
  • dostęp do zasobu będzie żądany z wielu, różnych części systemu.
  • może być tylko jeden obiekt.

Jeśli proponowany Singleton ma tylko jedno lub dwa z tych wymagań, przeprojektowanie jest prawie zawsze właściwą opcją.

Na przykład, spooler drukarki jest mało prawdopodobne, aby być wywołane z więcej niż jednego miejsca ( Menu wydruku), dzięki czemu możesz użyć mutexów do rozwiązania problemu współbieżnego dostępu.

Prosty rejestrator jest najbardziej oczywistym przykładem prawdopodobnie poprawnego Singletona, ale może się to zmienić przy bardziej złożonych schematach logowania.

 107
Author: metao,
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-10-23 01:59:20

Odczytywanie plików konfiguracyjnych, które powinny być odczytywane tylko podczas uruchamiania i zamykanie ich w Singletonie.

 38
Author: Paul Croarkin,
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-10-23 01:31:52

Używasz Singletona, gdy musisz zarządzać współdzielonym zasobem. Na przykład spooler drukarki. Twoja aplikacja powinna mieć tylko jedną instancję spoolera, aby uniknąć sprzecznych żądań dla tego samego zasobu.

Lub połączenie z bazą danych lub menedżer plików itp.

 31
Author: Vincent Ramdhanie,
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-10-23 01:21:32

Singletony tylko do odczytu przechowujące pewien globalny stan (język użytkownika, ścieżka pomocy, Ścieżka aplikacji) są rozsądne. Uważaj na używanie singletonów do kontrolowania logiki biznesowej-pojedynczy prawie zawsze kończy się wielokrotnością

 22
Author: Martin Beckett,
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-10-23 01:35:04

Zarządzanie połączeniem (lub pulą połączeń) do bazy danych.

Użyłbym go również do pobierania i przechowywania informacji o zewnętrznych plikach konfiguracyjnych.

 16
Author: Federico A. Ramponi,
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-10-23 01:25:49

Jednym ze sposobów użycia singletonu jest pokrycie instancji, w której musi istnieć pojedynczy "broker" kontrolujący dostęp do zasobu. Singletony są dobre w loggerach, ponieważ umożliwiają dostęp np. do pliku, do którego można pisać tylko i wyłącznie. W przypadku czegoś takiego jak logowanie, zapewniają sposób na abstrakcję zapisów do czegoś takiego jak plik dziennika - możesz zawinąć mechanizm buforowania do Singletona itp...

Pomyśl także o sytuacji, w której masz aplikację z wieloma oknami / wątkami / etc, ale które wymagają jednego punktu komunikacji. Kiedyś użyłem jednego do kontrolowania zadań, które chciałem uruchomić moją aplikację. Singleton był odpowiedzialny za serializację zadań i wyświetlanie ich statusu każdej innej części programu, która była zainteresowana. W takim scenariuszu możesz spojrzeć na singleton jako coś w rodzaju klasy "serwera" działającej wewnątrz Twojej aplikacji... HTH

 9
Author: Dave Markle,
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-10-23 01:26:20

Singleton powinien być używany podczas zarządzania dostępem do zasobu, który jest współdzielony przez całą aplikację, a potencjalnie posiadanie wielu instancji tej samej klasy byłoby destrukcyjne. Upewnienie się, że dostęp do współdzielonych zasobów thread safe jest bardzo dobrym przykładem tego, gdzie ten rodzaj wzorca może być kluczowy.

Podczas używania singletonów, należy upewnić się, że nie przypadkowo ukrywasz zależności. Idealnie, singletony (jak większość zmiennych statycznych w aplikacja) być skonfigurowane podczas wykonywania kodu inicjalizacyjnego dla aplikacji (static void Main() dla plików wykonywalnych C#, static void main() dla plików wykonywalnych java), a następnie przekazywane do wszystkich innych klas, które są utworzone instancje, które tego wymagają. Pomaga to utrzymać testowalność.

 9
Author: Adam Ness,
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-10-23 02:05:51

Praktyczny przykład Singletona można znaleźć w Test::Builder, klasie, która wspiera prawie każdy nowoczesny moduł testujący Perla. Test:: Builder singleton przechowuje i pośredniczy stan i historię procesu testowego (historyczne wyniki testów, zlicza liczbę uruchomionych testów), a także takie rzeczy, jak to, dokąd zmierza wynik testu. Są one niezbędne do skoordynowania wielu modułów testowych, napisanych przez różnych autorów, aby współpracować w jednym teście scenariusz.

Historia Test:: Builder ' s singleton jest edukacyjna. Wywołanie new() zawsze daje ten sam obiekt. Po pierwsze, wszystkie dane zostały zapisane jako zmienne klasy bez niczego w samym obiekcie. To działało, dopóki nie chciałem przetestować Test::Builder z samym sobą. Następnie potrzebowałem dwóch obiektów Test:: Builder, jednego ustawionego jako atrapa, aby przechwycić i przetestować jego zachowanie i wyjście, a jednego, aby był prawdziwym obiektem testowym. W tym momencie Test:: Builder został przekształcony w prawdziwy obiekt. Singleton obiekt był przechowywany jako dane klasy i new() zawsze go zwracał. create() został dodany, aby stworzyć świeży obiekt i umożliwić testowanie.

Obecnie użytkownicy chcą zmienić niektóre zachowania Test:: Builder we własnym module, ale pozostawić inne w spokoju, podczas gdy historia testów pozostaje wspólna dla wszystkich modułów testowych. To, co dzieje się teraz, to test monolityczny:: Builder obiekt jest podzielony na mniejsze części (historia, wyjście, format...) z testem:: Builder instance collecting razem. Teraz Test:: Builder nie musi już być singletonem. Jego składniki, jak historia, może być. To popycha nieelastyczną konieczność Singletona w dół poziomu. Daje to użytkownikowi większą elastyczność w mieszaniu i dopasowywaniu elementów. Mniejsze obiekty singleton mogą teraz po prostu przechowywać dane, a ich zawierające obiekty decydują o tym, jak z nich korzystać. Pozwala nawet na grę klasą non-Test::Builder, używając historii Test::Builder i singletonów wyjściowych.

Wydaje się, że jest pchnięcie i przeciągnij między koordynacją danych i elastycznością zachowania, które można złagodzić, umieszczając singleton wokół tylko udostępnionych danych z najmniejszą ilością zachowania, jak to możliwe, aby zapewnić integralność danych.

 6
Author: Schwern,
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-12-21 00:10:03

Myślę, że użycie Singletona może być traktowane jako to samo, co relacja many-to-one w bazach danych. Jeśli masz wiele różnych części kodu, które muszą pracować z pojedynczą instancją obiektu, to jest to, gdzie ma sens używanie singletonów.

 4
Author: daalbert,
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
2018-02-25 14:18:28

Jak wszyscy mówili, współdzielony zasób-w szczególności coś, co nie może obsłużyć współbieżnego dostępu.

Jeden konkretny przykład, który widziałem, jest Lucene Search Index Writer.

 3
Author: Mike,
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-10-23 01:33:20

Podczas ładowania obiektu configuration Properties, zarówno z bazy danych, jak i Pliku, pomaga mieć go jako singleton; nie ma powodu, aby ponownie czytać statyczne dane, które nie ulegną zmianie podczas działania serwera.

 3
Author: Dean J,
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-30 16:30:54

Wspólne zasoby. Szczególnie w PHP, Klasa bazy danych, klasa szablonu i klasa globalnej zmiennej depot. Wszystkie muszą być współdzielone przez wszystkie moduły / klasy, które są używane w całym kodzie.

Jest to prawdziwe użycie obiektu - > Klasa template zawiera szablon strony, który jest budowany, i jest kształtowany, dodawany, zmieniany przez moduły, które są dodawane do wyjścia strony. Musi być przechowywana jako pojedyncza instancja, aby tak się stało, podobnie jak w przypadku baz danych. Ze wspólnym bazy danych singleton, wszystkie klasy modułów mogą uzyskać dostęp do zapytań i uzyskać je bez konieczności ponownego ich uruchamiania.

Globalny magazyn zmiennych singleton zapewnia globalny, niezawodny i łatwy w użyciu magazyn zmiennych. Bardzo porządkuje Twój kod. Wyobraź sobie, że wszystkie wartości konfiguracyjne znajdują się w tablicy w singletonie, takiej jak $gb->config['hostname'] lub mają wszystkie wartości językowe w tablicy, takiej jak $gb->lang['ENTER_USER']. Pod koniec uruchomienia kodu strony, otrzymujesz, powiedzmy, dojrzały $template singleton, $gb singleton ma macierz lang do zastąpienia, a wszystkie dane wyjściowe są załadowane i gotowe. Wystarczy zamienić je na klucze, które są teraz obecne w wartości strony dojrzałego obiektu szablonu, a następnie podać je użytkownikowi.

Wielką zaletą tego jest to, że możesz wykonać dowolne przetwarzanie końcowe na czymkolwiek. Możesz przesłać wszystkie wartości językowe do Tłumacza google lub innej usługi tłumaczeniowej i odzyskać je i zastąpić je na ich miejsce, na przykład przetłumaczone. lub możesz zastąpić na stronie struktury, lub ciągi treści, jak chcesz.

 3
Author: Ozgur Zeren,
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
2018-02-25 14:20:32

Możesz użyć Singletona przy implementacji wzorca stanu(w sposób pokazany w książce GoF). Dzieje się tak dlatego, że konkretne klasy państwowe nie mają własnego stanu i wykonują swoje działania w kategoriach klasy kontekstowej.

Można również zrobić Abstract Factory singletonem.

 2
Author: Emile Cormier,
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-02-02 03:25:31

Bardzo pragmatyczne może być skonfigurowanie konkretnych problemów infrastrukturalnych jako singletonów lub zmiennych globalnych. Moim ulubionym przykładem są frameworki Dependency Injection, które wykorzystują singletony do działania jako punkt połączenia z frameworkiem.

W tym przypadku bierzesz zależność od infrastruktury, aby uprościć korzystanie z biblioteki i uniknąć niepotrzebnej złożoności.

 1
Author: smaclell,
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-10-23 01:35:30

Używam go do enkapsulacji parametrów wiersza poleceń w przypadku modułów pluggable. Główny program nie wie, jakie parametry wiersza poleceń są dla załadowanych modułów (i nie zawsze wie nawet, jakie moduły są ładowane). np. główne ładunki A, które same nie wymagają żadnych parametrów (więc dlaczego powinno wziąć dodatkowy wskaźnik / referencję / cokolwiek, nie jestem pewien - wygląda jak zanieczyszczenie), następnie ładuje Moduły X, Y i Z. dwa z nich, powiedzmy X i Z, muszą (lub accept) parametry, więc wywołują z powrotem do linii poleceń singleton, aby powiedzieć mu, jakie parametry mają zostać zaakceptowane, a w czasie wykonywania wywołują z powrotem, aby dowiedzieć się, czy użytkownik rzeczywiście podał któreś z nich.

Pod wieloma względami singleton do obsługi parametrów CGI działałby podobnie, jeśli używasz tylko jednego procesu na zapytanie (inne metody mod_* tego nie robią, więc byłoby to złe - stąd argument, który mówi, że nie powinieneś używać singletonów w świecie mod_cgi w przypadku portu do mod_perl czy jakikolwiek inny świat).

 0
Author: Tanktalus,
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-10-23 01:26:49

Przykład z kodem, być może.

Tutaj ConcreteRegistry jest singletonem w grze pokerowej, który umożliwia zachowanie aż do drzewa pakietów dostęp do kilku, podstawowych interfejsów gry (np. fasady dla modelu, widoku, kontrolera, środowiska itp.):

Http://www.edmundkirwan.com/servlet/fractal/cs1/frac-cs40.html

Ed.

 0
Author: ,
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-10-24 10:39:48

1-komentarz do pierwszej odpowiedzi:

Nie zgadzam się ze statyczną klasą Loggera. może to być praktyczne dla wdrożenia, ale nie może być wymienne dla testów jednostkowych. Klasy statycznej nie można zastąpić podwójnym testem. Jeśli nie test jednostkowy, nie zobaczysz problemu tutaj.

2-staram się nie tworzyć singletonu ręcznie. Po prostu tworzę prosty obiekt z konstruktorami, które pozwalają mi wstrzykiwać kolaborantów do obiektu. Gdybym potrzebował Singletona, użyłbym zależność w strukturze organizacyjnej (Spring.NET, Unity dla. NET, Spring dla Javy), czy innego.

 -8
Author: bloparod,
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-10-22 01:59:53