Wzorzec Singleton jest w pełni opłacone członek z GOF „s desenie książki , ale ostatnio wydaje się raczej osierocony przez świat dewelopera. Nadal używam całkiem wielu singletonów, szczególnie na zajęciach fabrycznych , i chociaż musisz być ostrożny w kwestii wielowątkowości (tak jak w przypadku każdej klasy), nie rozumiem, dlaczego są tak okropne.
Przepełnienie stosu wydaje się zakładać, że wszyscy zgadzają się, że Singletony są złe. Dlaczego?
Poprzyj swoje odpowiedzi „ faktami, referencjami lub specjalistyczną wiedzą ”
Odpowiedzi:
Parafrazowane przez Briana Buttona:
Są one na ogół używane jako instancja globalna, dlaczego to takie złe? Ponieważ ukrywasz zależności aplikacji w kodzie, zamiast ujawniać je za pośrednictwem interfejsów. Tworzenie czegoś globalnego, aby uniknąć przekazywania go, to zapach kodu .
Naruszają zasadę pojedynczej odpowiedzialności , ponieważ kontrolują własne stworzenie i cykl życia.
Z natury powodują ścisłe powiązanie kodu . To sprawia, że udawanie ich w testach jest w wielu przypadkach raczej trudne.
Niosą stan przez cały okres użytkowania aplikacji. Kolejne uderzenie w testowanie, ponieważ możesz skończyć z sytuacją, w której trzeba zamówić testy, co jest dużym „nie” dla testów jednostkowych. Dlaczego? Ponieważ każdy test jednostkowy powinien być niezależny od drugiego.
źródło
Singletony rozwiązują jeden (i tylko jeden) problem.
Spór o zasoby.
Jeśli masz jakieś zasoby, które
( 1 ) może mieć tylko jedną instancję i
( 2 ) musisz zarządzać tą pojedynczą instancją,
potrzebujesz singletona .
Nie ma wielu przykładów. Plik dziennika jest duży. Nie chcesz po prostu porzucić jednego pliku dziennika. Chcesz poprawnie przepłukać, zsynchronizować i zamknąć. To jest przykład pojedynczego zasobu udostępnionego, którym trzeba zarządzać.
Rzadko potrzebujesz singletona. Powodem, dla którego są źli, jest to, że czują się globalnie i są w pełni opłaconym członkiem książki GoF Design Patterns .
Kiedy myślisz, że potrzebujesz globalnej, prawdopodobnie popełnisz straszny błąd projektowy.
źródło
Niektóre kodujące snoby patrzą na nich z góry jak na gloryfikowany glob. W ten sam sposób, w jaki wiele osób nienawidzi oświadczenia goto , istnieją inne, które nienawidzą pomysłu korzystania z globalnego . Widziałem kilku programistów, którzy starali się uniknąć globalnego, ponieważ rozważali użycie jednego jako przyznania się do porażki. Dziwne ale prawdziwe.
W praktyce wzorzec Singleton jest tylko techniką programowania, która jest użyteczną częścią zestawu narzędzi pojęć. Od czasu do czasu może się okazać, że jest to idealne rozwiązanie, więc skorzystaj z niego. Ale używanie go tylko po to, aby pochwalić się użyciem wzorca projektowego, jest tak samo głupie, jak odmawianie jego użycia, ponieważ jest to po prostu globalny .
źródło
Misko Hevery z Google ma kilka interesujących artykułów na ten temat ...
Singletony są patologicznymi kłamcami ma przykładowy test jednostkowy, który ilustruje, w jaki sposób singletony mogą utrudnić określenie łańcuchów zależności oraz uruchomienie lub przetestowanie aplikacji. Jest to dość ekstremalny przykład znęcania się, ale jego uwaga jest nadal aktualna:
Tam, gdzie zniknęły wszystkie Singletony, chodzi o to, że zastrzyk zależności ułatwił uzyskanie wystąpień do konstruktorów, które ich wymagają, co zmniejsza podstawową potrzebę złych, globalnych Singletonów, które potępiły się w pierwszym artykule.
źródło
Myślę, że zamieszanie jest spowodowane tym, że ludzie nie znają prawdziwego zastosowania wzoru Singleton. Nie mogę tego wystarczająco podkreślić. Singleton nie jest wzorem do zawijania globali. Wzorca singletonu należy używać tylko w celu zagwarantowania, że w czasie wykonywania istnieje jedno i tylko jedno wystąpienie danej klasy .
Ludzie myślą, że Singleton jest zły, ponieważ używają go do globalizacji. To z powodu tego zamieszania patrzy się na Singletona z góry. Proszę nie mylić singletonów i globałów. Jeśli zostanie użyty zgodnie z przeznaczeniem, uzyskasz ekstremalne korzyści ze wzoru Singleton.
źródło
setInstance
metody.) To jednak nie ma znaczenia - to, że zaprzeczamy, że „potrzebny” singleton również nie wiedział dziwnej rzeczy o enkapsulacji lub co jest nie tak z zmienny stan globalny, więc pomocnie (?) zapewnił seterów dla każdego. pojedynczy. pole. (I tak, zdarza się. Bardzo często . Niemal każdy singleton, jaki kiedykolwiek widziałem na wolności, był zmienny z założenia i często zawstydzający.)goto
itp. Mogą one działać w wielu przypadkach, ale szczerze mówiąc, „działa” nie wystarczy - jeśli chcesz przeciwstawić się konwencjonalnej mądrości, lepiej być w stanie zademonstrować swoje podejście jest lepszy niż konwencjonalne rozwiązania. I jeszcze nie widziałem takiego przypadku dla wzoru Singleton.getInstance
metody o podobnej nazwie lub zapobiega temu druga instancja. Szczerze mówiąc, w tym momencie równie dobrze możesz nie mieć jednego wystąpienia.Jedną złą rzeczą związaną z singletonami jest to, że nie można ich bardzo łatwo przedłużyć. Zasadniczo 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 tego, jedna rzecz, 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 komukolwiek, kto ich potrzebuje, zamiast mieć bezpośredni dostęp do nich ... W przeciwnym razie, jeśli zdecydujesz się na wiele sposobów robienia tego, co robi singleton, będzie to raczej trudna do zmiany, ponieważ każda klasa zawiera zależność, jeśli uzyskuje bezpośredni dostęp do singletonu.
Więc w zasadzie:
zamiast:
Uważam, że tego rodzaju schemat nazywa się wstrzykiwaniem zależności i ogólnie uważa się go za dobrą rzecz.
Jak każdy wzór ... Pomyśl o tym i zastanów się, czy jego użycie w danej sytuacji jest niewłaściwe, czy nie ... Reguły są zwykle łamane, a wzorców nie należy bezmyślnie stosować.
źródło
getInstance()
, to (b) nie jest już do końca prawdą.getInstance()
skutecznie odrzuciłeś jedną użyteczną różnicę między wzorem Singleton a zwykłym odniesieniem. Jeśli chodzi o resztę kodu, pojedynczość nie jest już własnością. Tylko osoba dzwoniącagetInstance()
musi wiedzieć, a nawet dbać o liczbę wystąpień. Tylko jeden dzwoniący kosztuje więcej wysiłku i elastyczności, aby rzetelnie egzekwować jednolitość, niż przechowywanie po prostu numeru referencyjnego i ponowne użycie go.Wzorzec singletonu sam w sobie nie stanowi problemu. Problem polega na tym, że wzorzec jest często używany przez osoby opracowujące oprogramowanie z narzędziami obiektowymi, nie posiadające solidnego zrozumienia koncepcji OO. Kiedy singletony są wprowadzane w tym kontekście, stają się one klasami niemożliwymi do zarządzania, które zawierają metody pomocnicze dla każdego małego zastosowania.
Singletony są również problemem z punktu widzenia testowania. Zwykle utrudniają pisanie pojedynczych testów jednostkowych. Inwersja kontroli (IoC) i wstrzykiwanie zależności są wzorcami mającymi na celu przezwyciężenie tego problemu w sposób obiektowy, który nadaje się do testowania jednostkowego.
W środowisku śmieciowym 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.
źródło
Singleton jest implementowany przy użyciu metody statycznej. Ludzie, którzy przeprowadzają testy jednostkowe, unikają metod statycznych, ponieważ nie można ich wyśmiewać ani karczować. Większość osób na tej stronie jest wielkimi zwolennikami testów jednostkowych. Generalnie najbardziej akceptowaną konwencją, aby ich uniknąć, jest stosowanie odwrócenia wzorca kontroli .
źródło
Singleton
klasą. To jednak ogromnie komplikuje proces testowania. Po pierwsze, teraz musisz mieć możliwość zwolnienia klas do woli (tak naprawdę nie jest to opcja w większości języków) lub uruchomienia nowej maszyny wirtualnej dla każdego testu (czytaj: testy mogą trwać tysiące razy). Jednak dla dwóch osób zależnośćSingleton
jest szczegółem implementacji, który przecieka przez wszystkie testy.Singletony są również złe, jeśli chodzi o klastrowanie . Ponieważ wtedy nie ma już „dokładnie jednego singletonu” w aplikacji.
Rozważ następującą sytuację: Jako programista musisz utworzyć aplikację internetową, która uzyskuje dostęp do bazy danych. Aby upewnić się, że równoczesne wywołania bazy danych nie powodują konfliktów, należy utworzyć zapis wątków
SingletonDao
:Jesteś więc pewien, że w aplikacji istnieje tylko jeden singleton, a cała baza danych przechodzi przez ten jeden i tylko jeden
SingletonDao
. Twoje środowisko produkcyjne wygląda teraz tak:Jak dotąd wszystko jest w porządku.
Teraz rozważ, czy chcesz skonfigurować wiele instancji swojej aplikacji internetowej w klastrze. Teraz nagle masz coś takiego:
Brzmi dziwnie, ale teraz masz wiele singletonów w swojej aplikacji . I właśnie tym nie powinien być singleton: posiadanie wielu obiektów. Jest to szczególnie złe, jeśli, jak pokazano w tym przykładzie, chcesz wykonywać zsynchronizowane połączenia z bazą danych.
Oczywiście jest to przykład złego użycia singletonu. Ale przesłanie tego przykładu jest następujące: Nie można polegać na tym, że w aplikacji jest dokładnie jedno wystąpienie singletonu - szczególnie jeśli chodzi o klastrowanie.
źródło
źródło
Monopol to diabeł, a singletony ze stanem nieczytelnym / zmiennym są „prawdziwym” problemem ...
Po przeczytaniu Singletonów są Patologicznymi Kłamcami, jak zasugerowano w odpowiedzi Jasona, natknąłem się na ten mały smakołyk, który stanowi najlepiej przedstawiony przykład tego, jak singletony są często niewłaściwie wykorzystywane.
W ostatnim oświadczeniu nawiązuje do koncepcji blogu „singletony są kłamcami”.
Jak to się ma do Monopolu?
Aby rozpocząć grę w monopol, najpierw:
Dla każdego, kto tak naprawdę nie grał w monopol, standardy te są w najlepszym wypadku idealne. Porażka w monopolu jest trudna do przełknięcia, ponieważ w monopolu chodzi o pieniądze, jeśli przegrasz, musisz uważnie obserwować, jak reszta graczy kończy grę, a straty są zwykle szybkie i miażdżące. W związku z tym reguły zwykle ulegają zmianie w pewnym momencie, aby służyć interesom niektórych graczy kosztem innych.
Więc grasz w monopol z przyjaciółmi Bobem, Joe i Edem. Szybko budujesz swoje imperium i pochłaniasz udział w rynku w tempie wykładniczym. Twoi przeciwnicy słabną i zaczynasz wąchać krew (w przenośni). Twój kumpel Bob wkłada wszystkie swoje pieniądze w blokowanie jak największej liczby nieruchomości o niskiej wartości, ale nie osiąga wysokiego zwrotu z inwestycji w sposób, jakiego oczekiwał. Bob, jako powód pecha, ląduje na Boardwalk i zostaje usunięty z gry.
Teraz gra zmienia się z przyjaznego rzucania kostkami w poważny biznes. Bob został przykładem porażki, a Joe i Ed nie chcą skończyć jak „ten facet”. Będąc wiodącym graczem, nagle stajesz się wrogiem. Joe i Ed zaczynają ćwiczyć transakcje pod stołem, zastrzyki gotówki, niedowartościowane zamiany domów i ogólnie wszystko, co osłabi cię jako gracza, dopóki jeden z nich nie awansuje na szczyt.
Następnie, zamiast wygrania jednego z nich, proces zaczyna się od nowa. Nagle skończony zestaw zasad staje się ruchomym celem, a gra przeradza się w rodzaj interakcji społecznych, które stanowiłyby podstawę każdego wysoko ocenianego reality show od czasu Survivor. Dlaczego, ponieważ zasady się zmieniają i nie ma zgody co do tego, jak / dlaczego / co mają reprezentować, a co ważniejsze, nikt nie podejmuje decyzji. W tym momencie każdy gracz w grze ustanawia własne zasady i nastaje chaos, dopóki dwóch graczy nie będzie zbyt zmęczonych, aby nadążyć za szaradą i powoli się poddać.
Tak więc, jeśli zbiór reguł gry dokładnie reprezentowałby singletona, to zbiór reguł monopolu byłby przykładem nadużycia.
Jak to się ma do programowania?
Oprócz wszystkich oczywistych problemów związanych z bezpieczeństwem wątków i synchronizacją, które występują w mutowalnych singletonach ... Jeśli masz jeden zestaw danych, który może być odczytywany / manipulowany przez wiele różnych źródeł jednocześnie i istnieje przez cały czas wykonywania aplikacji, prawdopodobnie jest to dobry moment, aby cofnąć się i zapytać „czy używam tutaj odpowiedniej struktury danych”.
Osobiście widziałem, jak programiści nadużywają singletonu, używając go jako pewnego rodzaju skręconego sklepu z bazami danych w aplikacji. Pracując bezpośrednio nad kodem, mogę zaświadczyć, że był on powolny (z powodu wszystkich blokad wątków potrzebnych do zapewnienia bezpieczeństwa wątków) i koszmarem do pracy (z powodu nieprzewidywalnej / przerywanej natury błędów synchronizacji) oraz prawie niemożliwe do przetestowania w warunkach „produkcyjnych”. Jasne, można by opracować system wykorzystujący odpytywanie / sygnalizację w celu przezwyciężenia niektórych problemów z wydajnością, ale to nie rozwiązałoby problemów z testowaniem i po co zawracać sobie głowę tym, kiedy „prawdziwa” baza danych może już osiągnąć tę samą funkcjonalność w znacznie bardziej solidnej / sposób skalowalny.
Singleton jest opcją tylko , jeśli potrzebujesz tego, co zapewnia singleton. Wystąpienie obiektu tylko do odczytu dla obiektu. Ta sama reguła powinna również kaskadować do właściwości / elementów obiektu.
źródło
Singleton.getInstance()
. Język obsługujący odbicie może być w stanie obejść ten problem, ustawiając pole, w którym przechowywana jest jedna prawdziwa instancja. IMO jednak testy stają się nieco mniej wiarygodne, gdy zaczniesz ćwiczyć z prywatnym stanem innej klasy.Singleton nie dotyczy pojedynczego wystąpienia!
W przeciwieństwie do innych odpowiedzi, nie chcę rozmawiać o tym, co jest nie tak z Singletonami, ale pokazać wam, jak potężne i niesamowite są, gdy są właściwie stosowane!
Rozwiązanie : Użyj procesu jednowątkowego ładowania początkowego, aby zainicjować wszystkie zależności twojego singletona.
Rozwiązanie : Użyj metody Fabryczny wzór do kpienia
Możesz odwzorować
MyModel
naTestMyModel
dziedziczącą klasę, wszędzie tam, gdzieMyModel
zostanie wstrzyknięty, pojawi sięTestMyModel
instread. - Problem : Singletony mogą powodować wycieki pamięci, ponieważ nigdy nie zostały usunięte.Rozwiązanie : Pozbądź się ich! Zaimplementuj funkcję zwrotną w swojej aplikacji, aby poprawnie pozbyć się singletonów, powinieneś usunąć wszelkie powiązane z nimi dane i wreszcie: usunąć je z fabryki.
Jak wspomniałem w tytule singleton nie dotyczy pojedynczego wystąpienia.
źródło
Settings
obiekt singleton, który jest dostępny z dowolnego widgetu, dzięki czemu każdy widget wie, jak sformatować wyświetlane liczby. Gdyby nie był to obiekt dostępny na całym świecie, musiałbym wstrzyknąć go do konstruktora każdemu widgetowi w konstruktorze i zachować odniesienie do niego jako zmiennej składowej. To straszne marnowanie pamięci i czasu.Moja odpowiedź na temat tego, jak Singletonowie są źli, zawsze brzmi: „ciężko jest zrobić dobrze”. Wiele podstawowych składników języków to singletony (klasy, funkcje, przestrzenie nazw, a nawet operatory), podobnie jak komponenty w innych aspektach obliczeń (host lokalny, domyślna trasa, wirtualny system plików itp.) I nie jest to przypadek. Chociaż od czasu do czasu powodują kłopoty i frustrację, mogą również sprawić, że wiele rzeczy działa dużo lepiej.
Dwa największe błędy, które widzę to: traktowanie tego jak globalne i brak definicji zamknięcia singletonu.
Wszyscy mówią o Singletonach jako o globalsach, bo tak po prostu są. Jednak znaczna część (niestety nie wszystkie) zła w globalności nie wynika z samej bycia globalną, ale z tego, jak z niej korzystasz. To samo dotyczy singletonów. W rzeczywistości tym bardziej, że „pojedyncze wystąpienie” tak naprawdę nie musi oznaczać „globalnie dostępny”. Jest to bardziej naturalny produkt uboczny, a biorąc pod uwagę wszystkie znane nam zło, nie powinniśmy spieszyć się z wykorzystaniem globalnej dostępności. Gdy programiści zobaczą Singletona, wydają się zawsze uzyskiwać do niego bezpośredni dostęp za pomocą metody instancji. Zamiast tego powinieneś nawigować do niego tak, jak do każdego innego obiektu. Większość kodu nie powinna nawet zdawać sobie sprawy, że ma do czynienia z Singletonem (luźne sprzężenie, prawda?). Jeśli tylko niewielka część kodu uzyskuje dostęp do obiektu, tak jakby był globalny, wiele szkód zostaje cofniętych.
Bardzo ważny jest również kontekst Singleton. Cechą charakterystyczną Singletona jest to, że istnieje „tylko jeden”, ale prawda jest taka, że jest „tylko jeden” w jakimś kontekście / przestrzeni nazw. Zazwyczaj są to: jeden na wątek, proces, adres IP lub klaster, ale może być także jeden na procesor, maszynę, przestrzeń nazw języka / moduł ładujący klasy / cokolwiek, podsieć, Internet itp.
Innym, mniej powszechnym błędem jest ignorowanie stylu życia Singletona. To, że istnieje tylko jeden, nie oznacza, że Singleton jest jakimś wszechmocnym „zawsze był i zawsze będzie”, ani też nie jest ogólnie pożądany (obiekty bez początku i końca naruszają wszelkiego rodzaju użyteczne założenia w kodzie i powinny być stosowane tylko w najbardziej desperackich okolicznościach.
Jeśli unikniesz tych błędów, Singletony nadal mogą być PITA, ale jest gotowy, aby zobaczyć, że wiele najgorszych problemów zostanie znacznie złagodzonych. Wyobraź sobie Java Singleton, który jest jednoznacznie zdefiniowany jako jeden raz na moduł ładujący klasę (co oznacza, że potrzebuje polityki bezpieczeństwa wątków), ze zdefiniowanymi metodami tworzenia i niszczenia oraz cyklem życia, który określa, kiedy i jak mają być wywoływane, i którego metoda „instancji” ma ochrona pakietu, więc jest ogólnie dostępna za pośrednictwem innych, nieglobalnych obiektów. Nadal potencjalne źródło problemów, ale z pewnością znacznie mniej problemów.
Niestety, zamiast uczyć dobrych przykładów robienia singletonów. Uczymy złych przykładów, pozwalamy programistom na chwilę z nich korzystać, a następnie informujemy, że są złym wzorcem projektowym.
źródło
Zobacz Wikipedia Singleton_pattern
Referencje (tylko istotne odniesienia z artykułu)
źródło
To nie jest tak, że same singletony są złe, ale wzór projektu GoF jest. Jedynym naprawdę ważnym argumentem jest to, że wzorzec projektowy GoF nie nadaje się do testowania, zwłaszcza jeśli testy są uruchamiane równolegle.
Użycie pojedynczej instancji klasy jest prawidłową konstrukcją, o ile zastosujesz w kodzie następujące środki:
Upewnij się, że klasa, która będzie używana jako singleton, implementuje interfejs. Umożliwia to implementację kodów pośredniczących lub próbnych przy użyciu tego samego interfejsu
Upewnij się, że Singleton jest bezpieczny dla wątków. To jest dane.
Singleton powinien być z natury prosty i niezbyt skomplikowany.
Podczas działania aplikacji, w której singletony muszą zostać przekazane do danego obiektu, użyj fabryki klas, która buduje ten obiekt, i pozwól, aby fabryka klas przekazała instancję singletonu do klasy, która tego potrzebuje.
Podczas testowania i w celu zapewnienia deterministycznego zachowania utwórz klasę singleton jako osobną instancję jako samą klasę lub stub / mock, który implementuje swoje zachowanie i przekazuje ją niezmienionej klasie, która tego wymaga. Nie używaj współczynnika klasy, który tworzy testowany obiekt, który potrzebuje singletonu podczas testu, ponieważ przejdzie on przez jedną globalną instancję tego obiektu, która nie spełnia celu.
W naszych rozwiązaniach wykorzystaliśmy Singletony z dużym sukcesem, który można przetestować, zapewniając deterministyczne zachowanie w równoległych strumieniach testowych.
źródło
Chciałbym odnieść się do 4 punktów w przyjętej odpowiedzi, mam nadzieję, że ktoś może wyjaśnić, dlaczego się mylę.
Dlaczego ukrywanie zależności w kodzie jest złe? Istnieją już dziesiątki ukrytych zależności (wywołania środowiska wykonawczego C, wywołania interfejsu API systemu operacyjnego, wywołania funkcji globalnych), a zależności singletonu są łatwe do znalezienia (wyszukaj na przykład ()).
„Tworzenie czegoś globalnego, aby uniknąć przekazywania go, to zapach kodu”. Dlaczego nie podaje się czegoś, by nie sprawić, by singleton miał zapach kodu?
Jeśli przepuszczasz obiekt przez 10 funkcji w stosie wywołań tylko po to, aby uniknąć singletonu, czy to takie wspaniałe?
Zasada pojedynczej odpowiedzialności: Myślę, że jest to nieco niejasne i zależy od twojej definicji odpowiedzialności. Istotne byłoby pytanie, dlaczego dodanie tej konkretnej „odpowiedzialności” do sprawy klasowej?
Dlaczego przekazanie obiektu do klasy powoduje, że jest on ściślej sprzężony niż używanie tego obiektu jako singletonu z klasy?
Dlaczego zmienia to, jak długo trwa stan? Singletony mogą być tworzone lub niszczone ręcznie, więc kontrola jest nadal dostępna i możesz ustawić czas życia taki sam, jak trwałość obiektu nie będącego singletonem.
Odnośnie testów jednostkowych:
źródło
Vince Huston ma następujące kryteria, które wydają mi się rozsądne:
źródło
Singletony są złe z purystycznego punktu widzenia.
Z praktycznego punktu widzenia singleton jest kompromisem między czasem rozwoju a złożonością .
Jeśli wiesz, że twoja aplikacja nie zmieni się aż tak bardzo, jest całkiem w porządku. Po prostu wiedz, że może być konieczne przefakturowanie rzeczy, 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 .
źródło
Wzorzec ten nie ma z natury nic złego, zakładając, że jest on używany do pewnego aspektu twojego modelu, który jest naprawdę pojedynczy.
Uważam, że luz jest spowodowany jego nadmiernym wykorzystaniem, które z kolei wynika z faktu, że jest to najłatwiejszy wzór do zrozumienia i wdrożenia.
źródło
Nie zamierzam komentować argumentu dobro / zło, ale nie użyłem ich od wiosny . Używanie wstrzykiwania zależności prawie całkowicie usunęło moje wymagania dotyczące singletonów, serwisantów i fabryk. Uważam, że jest to o wiele bardziej produktywne i czyste środowisko, przynajmniej dla rodzaju wykonywanej pracy (aplikacje internetowe oparte na Javie).
źródło
Singleton jest wzorem i może być używany lub nadużywany tak jak każde inne narzędzie.
Złą częścią singletonu jest na ogół użytkownik (lub powinienem powiedzieć niewłaściwe użycie singletona do rzeczy, do których nie jest przeznaczony). Największy przestępca wykorzystuje singletona jako fałszywą zmienną globalną.
źródło
Kiedy piszesz kod za pomocą singletonów, powiedzmy, programu rejestrującego lub połączenia z bazą danych, a potem okazuje się, że potrzebujesz więcej niż jednego dziennika lub więcej niż jednej bazy danych, masz kłopoty.
Singletony bardzo utrudniają przejście od nich do zwykłych przedmiotów.
Ponadto zbyt łatwo jest napisać singleton, który nie jest bezpieczny dla wątków.
Zamiast używać singletonów, należy przekazać wszystkie potrzebne obiekty narzędziowe z funkcji do funkcji. Można to uprościć, jeśli owiniesz je wszystkie w obiekt pomocnika, taki jak ten:
źródło
Problemy z singletonami polegają na zwiększeniu zakresu, a zatem sprzężenia . Nie można zaprzeczyć, że istnieją sytuacje, w których potrzebujesz dostępu do jednej instancji, i można to zrobić na inne sposoby.
Teraz wolę projektować wokół kontenera z inwersją sterowania (IoC) i pozwalać na kontrolowanie żywotności kontenera. Daje to korzyści klasom zależnym od instancji, które nie są świadome faktu, że istnieje jedna instancja. Czas życia singletonu można zmienić w przyszłości. Kiedyś takim przykładem, z którym ostatnio się spotkałem, była łatwa regulacja od jednowątkowego do wielowątkowego.
FWIW, jeśli jest to PIA, gdy próbujesz ją przetestować, to przejdzie do PIA, gdy spróbujesz debugować, naprawić błąd lub go ulepszyć.
źródło
Ostatni artykuł na ten temat autorstwa Chrisa Reatha w Coding Without Comments .
Uwaga: Kodowanie bez komentarzy nie jest już ważne. Jednak artykuł, do którego prowadzi link, 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
źródło
Singletony NIE są złe. Jest to złe tylko wtedy, gdy tworzysz coś globalnie wyjątkowego, co nie jest globalnie wyjątkowe.
Istnieją jednak „usługi zakresu aplikacji” (pomyśl o systemie przesyłania komunikatów, który umożliwia interakcję komponentów) - to WEZWANIE dla singletona, „MessageQueue” - klasa, która ma metodę „SendMessage (...)”.
Następnie możesz wykonać następujące czynności z całego miejsca:
MessageQueue.Current.SendMessage (new MailArrivedMessage (...));
I oczywiście:
MessageQueue.Current.RegisterReceiver (this);
w klasach, które implementują IMessageReceiver.
źródło
Zbyt wiele osób umieszcza obiekty, które nie są bezpieczne dla wątków, według wzoru singletonu. Widziałem przykłady DataContext ( LINQ do SQL ) wykonane we wzorcu singletonowym, pomimo faktu, że DataContext nie jest bezpieczny dla wątków i jest obiektem czysto jednostkowym.
źródło
Oto jeszcze jedna rzecz o singletonach, o której nikt jeszcze nie powiedział.
W większości przypadków „singletonity” jest szczegółem implementacji dla niektórych klas, a nie cechą interfejsu. Odwrócenie kontenera sterującego może ukryć tę właściwość przed użytkownikami klasy; wystarczy zaznaczyć swoją klasę jako singleton (
@Singleton
na przykład z adnotacją w Javie) i to wszystko; IoCC zajmie się resztą. Nie musisz zapewniać globalnego dostępu do instancji singleton, ponieważ dostęp jest już zarządzany przez IoCC. Dlatego nie ma nic złego w IoC Singletons.GoF Singletons w przeciwieństwie do IoC Singletons mają ujawniać „singletonity” w interfejsie za pomocą metody getInstance (), tak aby cierpiały na wszystko, co powiedziano powyżej.
źródło
Singletony nie są złe, jeśli używasz ich właściwie i minimalnie . Istnieje wiele innych dobrych wzorców projektowych, które w pewnym momencie zastępują potrzeby singletonu (i dają również najlepsze wyniki). Ale niektórzy programiści nie są świadomi tych dobrych wzorców i używają singletonu we wszystkich przypadkach, co czyni singletona złymi dla nich.
źródło
Po pierwsze, klasa i jej współpracownicy powinni najpierw wykonać zamierzony cel, zamiast koncentrować się na osobach zależnych. Zarządzanie cyklem życia (gdy tworzone są instancje i kiedy wykraczają one poza zakres) nie powinny wchodzić w zakres odpowiedzialności klas. Zaakceptowaną najlepszą praktyką jest tworzenie lub konfigurowanie nowego komponentu do zarządzania zależnościami za pomocą wstrzykiwania zależności.
Często oprogramowanie staje się bardziej skomplikowane, dlatego sensowne jest posiadanie wielu niezależnych instancji klasy Singleton o różnych stanach. W takich przypadkach popełnianie kodu, aby po prostu chwycić singletona, jest błędne. Za pomocą
Singleton.getInstance()
może być odpowiednie dla małych prostych systemów, ale nie działa / nie skaluje się, gdy można potrzebować innej instancji tej samej klasy.Żadna klasa nie powinna być traktowana jako singleton, ale raczej powinna być aplikacją, w której jest używana lub w jaki sposób służy do konfigurowania zależności. Dla szybkiego i nieprzyjemnego nie ma to znaczenia - tylko luźne kodowanie mówi, że ścieżki plików nie mają znaczenia, ale w przypadku większych aplikacji takie zależności muszą być uwzględnione i zarządzane w bardziej odpowiedni sposób za pomocą DI.
Problemy, które singleton powoduje w testach, są symptomem ich zakodowanego pojedynczego przypadku użycia / środowiska. Zestaw testowy i wiele testów są z osobna i oddzielają coś, co nie jest kompatybilne z kodowaniem pojedynczym singletona.
źródło
Ponieważ są to zasadniczo zmienne globalne zorientowane obiektowo, zazwyczaj można zaprojektować swoje klasy w taki sposób, aby nie były potrzebne.
źródło