Po co używać singletona zamiast metod statycznych?

93

Nigdy nie znalazłem dobrych odpowiedzi na te proste pytania dotyczące klas pomocniczych / użytkowych:

Dlaczego miałbym utworzyć singleton (bezstanowy) zamiast używać metod statycznych?

Po co byłoby potrzebne wystąpienie obiektu, skoro obiekt nie ma stanu?

Sebastien Lorber
źródło
Nie myśl, ponieważ mówimy o 2 różnych językach, więc odpowiedź może się różnić, ale dzięki za link, w Javie nigdy nie słyszałem terminu „monostat”
Sebastien Lorber,

Odpowiedzi:

79

Często singletony są używane do wprowadzenia jakiegoś stanu globalnego do aplikacji. (Szczerze mówiąc, częściej niż jest to konieczne, ale to temat na inny raz.)

Istnieje jednak kilka narożnych przypadków, w których nawet bezstanowy singleton może być przydatny:

  • Spodziewasz się, że w dającej się przewidzieć przyszłości rozszerzyć go o stan.
  • Potrzebujesz instancji obiektu z jakiegoś szczególnego powodu technicznego .
    Przykład: obiekty synchronizacji dla instrukcji C # locklub Java synchronized.
  • Potrzebujesz dziedziczenia, tj. Chcesz mieć możliwość łatwej zamiany swojego singletona na inny z tym samym interfejsem, ale inną implementacją.
    Przykład: Toolkit.getDefaultToolkit()metoda w Javie zwróci singleton, którego dokładny typ zależy od systemu.
  • Chcesz równości odniesień dla wartości wartowniczej .
    Przykład: DBNull.Valuew C #.
Heinzi
źródło
27
Pójdę z +1, chociaż singletony IMHO są nadużywane do wprowadzania stanów globalnych. Celem singletona nie jest zapewnienie globalnej dostępności obiektu, ale wymuszenie, że obiekt jest tworzony tylko raz. Globalne obiekty są złem koniecznym. O ile nie jest to naprawdę wymagane, należy starać się ich nie używać, ponieważ generalnie prowadzą one do wysokiego sprzężenia, z SomeSingleton.getInstance (). SomeMethod () w każdym miejscu. :)
back2dos
Może to być przydatne w grach, w których potrzebujesz tylko jednej instancji renderującej zamiast wielu instancji renderowania, lub w przypadku klasy potoku sieciowego, w której konfigurujesz bezpieczny kanał, w którym może być tylko jedno połączenie naraz.
Tschallacka
2
Z mojego punktu widzenia najważniejsza jest część „łatwo wymienić singleton”. Reszta jest bardzo zbliżona do implementacji klasy statycznej.
Teoman shipahi
1
Singletony są użytecznymi wartościami wartowniczymi innymi niż Null dla typów sum / produktów i podobnych. Na przykład wartość None / Nothing w typie Option lub wartość Empty dla typu kolekcji. Otrzymujesz szybkie testowanie Brak / Puste jako bonus, ponieważ równość odniesień jest wszystkim, czego potrzebujesz.
jegobruce
@itsbruce: Twoje przykłady nie są singletonami : pusta lista nie jest jedyną możliwą instancją klasy List, a wartość None nie jest jedyną możliwą instancją klasy Option. Istnieją jednak przykłady, w których wartość wartownicza to pojedyncze wartości i pozwoliłem sobie dodać jeden do mojej odpowiedzi. Dzięki za wprowadzenie!
Heinzi
37

Mogłem zobaczyć przypadek użycia bezstanowego singletona zamiast statycznej klasy metod, a mianowicie dla Dependency Injection .

Jeśli masz pomocniczą klasę funkcji narzędziowych, których używasz bezpośrednio, tworzy ona ukrytą zależność; nie masz kontroli nad tym, kto może go używać i gdzie. Wstrzyknięcie tej samej klasy pomocniczej za pośrednictwem bezstanowej pojedynczej instancji pozwala kontrolować, gdzie i jak jest używana, a także zastępować ją / mockować / itp., Kiedy trzeba.

Uczynienie go pojedynczym wystąpieniem zapewnia po prostu, że nie przydzielasz więcej obiektów tego typu niż to konieczne (ponieważ potrzebujesz tylko jednego).

tzaman
źródło
1
„nie masz kontroli nad tym, kto może go używać i gdzie”. Dlaczego ktoś miałby tego potrzebować?
hagrawal
1
@hagrawal do celów testowych, powinieneś być w stanie z niego kpić
Jemshit Iskenderov
15

Właściwie znalazłem inną odpowiedź, o której tutaj nie wspomniano: metody statyczne są trudniejsze do przetestowania.

Wygląda na to, że większość frameworków testowych świetnie sprawdza się przy mockowaniu metod instancji, ale wiele z nich nie radzi sobie w przyzwoity sposób z mockowaniem metod statycznych.

Sebastien Lorber
źródło
2
Ale Powermock wydaje się być w stanie to zrobić
Sebastien Lorber
6

W większości zajęć z języków programowania wymyka się wiele z systemu typów. Chociaż klasa ze swoimi statycznymi metodami i zmiennymi jest obiektem, bardzo często nie może implementować interfejsu ani rozszerzać innych klas. Z tego powodu nie może być stosowany w sposób polimorficzny, ponieważ nie może być podtypem innego typu. Na przykład, jeśli masz interfejs IFooable, który jest wymagany przez kilka sygnatur metod innych klas, obiekt klasy StaticFoonie może być używany zamiast IFooable, podczas gdy FooSingleton.getInstance()can (zakładając, FooSingletonimplementuje IFooable).

Proszę zauważyć, że tak jak skomentowałem odpowiedź Heinziego, singleton jest wzorcem kontrolującym instancję. Zastępuje new Class()się Class.getInstance(), co daje autorowi Classwiększą kontrolę nad przypadkach, które może wykorzystać w celu zapobiegania tworzenia zbędnych przypadkach. Singleton to po prostu bardzo szczególny przypadek wzorca fabrycznego i tak powinien być traktowany. Powszechne użycie sprawia, że ​​jest to raczej szczególny przypadek rejestrów globalnych, co często kończy się błędem, ponieważ rejestry globalne nie powinny być używane tylko dla woli.

Jeśli planujesz zapewnić globalne funkcje pomocnicze, metody statyczne będą działać dobrze. Klasa nie będzie działać jako klasa, ale raczej jako przestrzeń nazw. Sugeruję, abyś zachował wysoką spójność, albo możesz skończyć z najdziwniejszymi problemami z połączeniem.

greetz
back2dos

back2dos
źródło
4

Istnieje kompromis między używaniem tego. Singletony mogą mieć stan lub nie i odnoszą się do obiektów. Jeśli nie zachowują stanu i są używane tylko do dostępu globalnego, statyczne jest lepsze, ponieważ te metody będą szybsze. Ale jeśli chcesz wykorzystać obiekty i koncepcje OOP (polimorfizm dziedziczenia), to singleton jest lepszy.

Rozważmy przykład: java.lang.Runtime to klasa pojedyncza w java. Ta klasa umożliwia różne implementacje dla każdej maszyny JVM. Implementacja jest pojedyncza na JVM. Gdyby ta klasa była statyczna, nie możemy przekazać różnych implementacji opartych na JVM.

Ten link okazał się bardzo pomocny: http://javarevisited.blogspot.com/2013/03/difference-between-singleton-pattern-vs-static-class-java.html ?

Mam nadzieję, że to pomoże!!

Atihska
źródło
Ta odpowiedź jest dobra, aby uwzględnić konkretny przykład w prawdziwym świecie.
systemovich
2

Dla mnie „Want Object State użyj Singleton, Want Function użyj metody statycznej”

To zależy od tego, czego chcesz. Ilekroć chcesz mieć stan obiektu (np. Polimorfizm, taki jak stan Null zamiast nulllub stan domyślny), singleton jest odpowiednim wyborem dla Ciebie, podczas gdy metoda statyczna jest używana, gdy potrzebujesz funkcji (odbieraj dane wejściowe, a następnie zwracaj dane wyjściowe).

Polecam w przypadku singletona, po utworzeniu instancji powinien być zawsze w tym samym stanie. Nie powinien być klonowalny ani przyjmować żadnej wartości do ustawienia (z wyjątkiem statycznej konfiguracji z pliku, np. Pliku właściwości w java).

PS Wydajność między tymi dwoma różni się w milisekundach, więc najpierw skup się na architekturze .

Toomtarm Kung
źródło
1

Singleton nie jest bezstanowy, posiada stan globalny.

Oto kilka powodów, dla których przychodzi mi do głowy używanie Singleton:

  • Aby uniknąć wycieków pamięci
  • Zapewnienie tego samego stanu dla wszystkich modułów w aplikacji, np. Połączenia z bazą danych
Indigo Praveen
źródło
Wiem, ale tak naprawdę singleton może być mniej więcej bezpaństwowy ... Jeśli nie ma żadnego atrybutu klasy ...
Sebastien Lorber