Nazwij względy projektowe przy podejmowaniu decyzji między użyciem pojedynczej a statycznej klasy. Robiąc to, jesteś jakby zmuszony do przeciwstawienia sobie obu, więc wszelkie kontrasty, które możesz wymyślić, są również przydatne w pokazaniu twojego procesu myślowego! Ponadto każdy ankieter lubi oglądać ilustracyjne przykłady. :)
design-patterns
cdleary
źródło
źródło
Odpowiedzi:
źródło
A co powiesz na „unikanie obu”? Singletony i klasy statyczne:
Zamiast tego zapoznaj się z bibliotekami Dependency Injection i Inversion of Control Container . Kilka bibliotek IoC zajmie się zarządzaniem przez cały okres użytkowania.
(Jak zawsze, istnieją wyjątki, takie jak statyczne klasy matematyczne i metody rozszerzające C #).
źródło
Hide Dependencies
Małe informacje dodatkowe na ten temat: Możesz zaimplementować wzorzec Inversion of Control, na przykład za pomocą Ninject . Pozwala to na użycie tylko jednej instancji typu przez powiązanie jej z aSingletonScope
, co oznacza, że zawsze będzie wstrzykiwać tę samą instancję, ale klasa nie będzie pojedyncza.Twierdzę, że jedyną różnicą jest składnia: MySingleton.Current.Whthing () vs MySingleton.Whthing (). Stan, jak wspomniał Dawid, jest ostatecznie „statyczny” w obu przypadkach.
EDYCJA: Brygada bury przyszła z digg ... w każdym razie pomyślałem o przypadku, który wymagałby singletona. Klasy statyczne nie mogą dziedziczyć z klasy bazowej ani implementować interfejsu (przynajmniej w .Net nie mogą). Więc jeśli potrzebujesz tej funkcjonalności, musisz użyć singletona.
źródło
Jedna z moich ulubionych dyskusji na ten temat znajduje się tutaj (oryginalna witryna wyłączona, teraz połączona z Internet Archive Wayback Machine ).
Podsumowując zalety elastyczności Singletona:
źródło
Klasa statyczna z ładunkiem zmiennych statycznych to trochę hack.
Singleton z aktualną instancją jest lepszy.
Stan jest TYLKO w instancji.
Tak więc singleton może zostać później zmodyfikowany, aby wykonać pulę, wystąpienia lokalne wątku itp. I żaden z już napisanych kodów nie musi być zmieniany, aby uzyskać korzyści.
Możliwe jest zrobienie czegoś podobnego z klasą statyczną, ale w pośrednim wysyłaniu będzie narzut na wywołanie.
Możesz pobrać instancję i przekazać ją do funkcji jako argument. Pozwala to na przekierowanie kodu do „właściwego” singletona. Wiemy, że będziesz potrzebować tylko jednego ... dopóki tego nie zrobisz.
Dużą zaletą jest to, że stanowe singletony mogą być bezpieczne dla wątków, podczas gdy statyczna klasa nie może, chyba że zmodyfikujesz ją tak, aby była tajnym singletonem.
źródło
Pomyśl o singletonie jak o usłudze. Jest to obiekt, który zapewnia określony zestaw funkcjonalności. Na przykład
Fabryka obiektów to obiekt, który wykonuje określoną usługę.
Z kolei klasa pełna metod statycznych to zbiór działań, które możesz chcieć wykonać, zorganizowanych w powiązaną grupę (Klasa). Na przykład
Przykład StringUtils tutaj to zbiór funkcji, które można zastosować w dowolnym miejscu. Pojedynczy obiekt fabryki to szczególny typ obiektu z wyraźną odpowiedzialnością, który można tworzyć i przekazywać w razie potrzeby.
źródło
Instancje klas statycznych są tworzone w czasie wykonywania. Może to zająć dużo czasu. Wystąpienie singletonów można utworzyć tylko w razie potrzeby.
źródło
Nie należy używać singletonów w taki sam sposób, jak klas statycznych. W istocie
jest zasadniczo taki sam jak
W rzeczywistości powinieneś traktować singletona jako kolejny obiekt . Jeśli usługa wymaga wystąpienia typu singleton, przekaż to wystąpienie w konstruktorze:
Usługa nie powinna być świadoma, że obiekt jest singletonem i powinna traktować obiekt tylko jako obiekt.
Obiekt z pewnością można zaimplementować, jako szczegół implementacji i jako aspekt ogólnej konfiguracji, jako singleton, jeśli to ułatwia. Ale rzeczy, które używają obiektu, nie powinny wiedzieć, czy obiekt jest singletonem, czy nie.
źródło
Jeśli przez „klasę statyczną” masz na myśli klasę, która ma tylko zmienne statyczne, to faktycznie mogą one utrzymywać stan. Rozumiem, że jedyną różnicą byłby sposób dostępu do tej rzeczy. Na przykład:
przeciw
Elementy wewnętrzne MySingleton będą oczywiście różne między nimi, ale pomijając kwestie bezpieczeństwa wątków, oba będą działać tak samo w odniesieniu do kodu klienta.
źródło
Wzorzec singleton jest zwykle używany do obsługi danych niezależnych lub statycznych, w przypadku których wiele wątków może uzyskiwać dostęp do danych w tym samym czasie. Jednym z przykładów mogą być kody stanów.
źródło
Nigdy nie należy używać singletonów (chyba że uznajesz klasę bez stanu mutowalnego za singleton). „Klasy statyczne” nie powinny mieć żadnego zmiennego stanu, z wyjątkiem być może pamięci podręcznych bezpiecznych dla wątków i tym podobnych.
Prawie każdy przykład singletona pokazuje, jak tego nie robić.
źródło
Jeśli singleton jest czymś, czego możesz się pozbyć, aby po nim posprzątać, możesz go rozważyć, gdy jest to ograniczony zasób (tj. Tylko 1 z nich), którego nie potrzebujesz przez cały czas i masz jakąś pamięć lub koszt zasobów, gdy jest przydzielony.
Kod czyszczenia wygląda bardziej naturalnie, gdy masz singleton, w przeciwieństwie do klasy statycznej zawierającej statyczne pola stanu.
Kod będzie jednak wyglądał tak samo w obu przypadkach, więc jeśli masz bardziej szczegółowe powody, by zapytać, być może powinieneś to rozwinąć.
źródło
Oba mogą być całkiem podobne, ale pamiętaj, że prawdziwy Singleton musi sam zostać utworzony (raz przyznany), a następnie obsłużony. Klasa bazy danych PHP, która zwraca instancję
mysqli
nie jest tak naprawdę Singletonem (jak niektórzy ją nazywają), ponieważ zwraca instancję innej klasy, a nie instancję klasy, której instancja jest statycznym składnikiem.Tak więc, jeśli piszesz nową klasę, dla której planujesz zezwolić tylko na jedną instancję w swoim kodzie, równie dobrze możesz napisać ją jako singleton. Pomyśl o tym jak o napisaniu zwykłej klasy i dodaniu do niej, aby ułatwić spełnienie wymagania pojedynczej instancji. Jeśli używasz cudzej klasy, której nie możesz modyfikować (np.
mysqli
), Powinieneś używać klasy statycznej (nawet jeśli nie uda ci się poprzedzić jej definicji słowem kluczowym).źródło
Singletony są bardziej elastyczne, co może być przydatne w przypadkach, gdy chcesz, aby metoda Instance zwracała różne konkretne podklasy typu Singleton w oparciu o pewien kontekst.
źródło
Klasy statyczne nie mogą być przekazywane jako argumenty; instancje singletona mogą być. Jak wspomniano w innych odpowiedziach, zwróć uwagę na problemy z wątkami w klasach statycznych.
rp
źródło
Singleton może mieć konstruktor i destruktor. W zależności od języka, konstruktor może być wywoływany automatycznie przy pierwszym użyciu singletona lub nigdy, jeśli singleton w ogóle nie jest używany. Klasa statyczna nie miałaby takiej automatycznej inicjalizacji.
Po uzyskaniu odniesienia do pojedynczego obiektu można go używać tak jak każdego innego obiektu. Kod klienta może nawet nie potrzebować wiedzieć, że używa singletona, jeśli odwołanie do singletona jest zapisane wcześniej:
To oczywiście ułatwia sprawę, gdy zdecydujesz się porzucić wzór Singleton na rzecz prawdziwego wzoru, takiego jak IoC.
źródło
Użyj wzorca singleton, gdy musisz obliczyć coś w czasie wykonywania, co gdybyś mógł obliczyć w czasie kompilacji, na przykład tabele odnośników.
źródło
Myślę, że miejsce, w którym Singleton będzie miał więcej sensu niż klasa statyczna, jest wtedy, gdy musisz zbudować pulę kosztownych zasobów (takich jak połączenia z bazą danych). Nie byłbyś zainteresowany tworzeniem puli, gdyby nikt nigdy ich nie używał (klasa statyczna oznacza, że wykonujesz kosztowną pracę, gdy klasa jest ładowana).
źródło
Singleton jest również dobrym pomysłem, jeśli chcesz wymusić wydajne buforowanie danych. na przykład mam klasę, która wyszukuje definicje w dokumencie xml. Ponieważ analiza dokumentu może trochę potrwać, skonfigurowałem pamięć podręczną definicji (używam SoftReferences, aby uniknąć outOfmemeoryErrors). Jeśli pożądanej definicji nie ma w pamięci podręcznej, wykonuję kosztowne analizowanie XML. W przeciwnym razie zwracam kopię z pamięci podręcznej. Ponieważ posiadanie wielu pamięci podręcznych oznaczałoby, że nadal może być konieczne wielokrotne ładowanie tej samej definicji, potrzebuję statycznej pamięci podręcznej. Zdecydowałem się zaimplementować tę klasę jako singleton, aby móc napisać klasę tylko przy użyciu zwykłych (niestatycznych) elementów członkowskich danych. Dzięki temu mogę nadal tworzyć analizę klasy, jeśli z jakiegoś powodu będę jej potrzebować (serializacja, testy jednostkowe itp.)
źródło
Singleton jest jak usługa, jak już wspomniano. Pro to jego elastyczność. Statyczne, potrzebujesz trochę statycznych części, aby zaimplementować Singleton.
Singleton ma kod, który zajmuje się tworzeniem instancji rzeczywistego obiektu, co może być bardzo pomocne, jeśli napotkasz problemy z wyścigami. W rozwiązaniu statycznym może być konieczne rozwiązanie problemów związanych z wyścigami w wielu lokalizacjach kodu.
Jednak tak samo jak Singleton można skonstruować z niektórymi zmiennymi statycznymi, możesz porównać go z „goto”. Może być bardzo przydatne do budowania innych konstrukcji, ale naprawdę musisz wiedzieć, jak z niego korzystać i nie należy go „nadużywać”. Dlatego generalnie zaleca się trzymanie się Singletona i używanie statycznego, jeśli trzeba.
sprawdź też inny post: Po co wybierać klasę statyczną zamiast implementacji singletona?
źródło
odnieś to
Podsumowanie:
za. Jedną z prostych praktycznych zasad, których możesz się kierować, jest to, że jeśli nie ma potrzeby utrzymywania stanu, możesz użyć klasy Static, w przeciwnym razie powinieneś użyć klasy Singleton.
b. użyj Singletona, jeśli jest to szczególnie „ciężki” przedmiot. Jeśli twój obiekt jest duży i zajmuje rozsądną ilość pamięci, wiele wywołań n / w (pula połączeń) ... itd. Aby upewnić się, że jego wystąpienie nie zostanie utworzone wiele razy. Klasa Singleton pomoże zapobiec takim przypadkom w przyszłości
źródło
Kiedy jedna klasa potrzebuje stanu. Singletony utrzymują stan globalny, klasy statyczne nie.
Na przykład, tworzenie pomocnika wokół klasy rejestru: Jeśli masz zmienną gałąź (HKey Current User vs HKEY Local Machine), możesz:
Teraz wszelkie dalsze wywołania tego singletona będą działać w gałęzi komputera lokalnego. W przeciwnym razie, używając klasy statycznej, musisz określić tę gałąź Everytiem komputera lokalnego lub mieć metodę taką jak
ReadSubkeyFromLocalMachine
.źródło