Różnica między klasą statyczną a wzorem singletonu?

1767

Jaka jest prawdziwa (tj. Praktyczna) różnica między klasą statyczną a wzorem singletonu?

Oba mogą być wywoływane bez tworzenia instancji, oba zapewniają tylko jedno „wystąpienie” i żadne z nich nie jest bezpieczne dla wątków. Czy jest jakaś inna różnica?

Jorge Córdoba
źródło
4
W zależności od implementacji języka i wzorców użytkowania Singleton może być mniej wydajny ze względu na narzut związany z wywoływaniem getInstance()metody za każdym razem, gdy chcesz jej użyć (chociaż prawdopodobnie w większości przypadków nie ma to znaczenia ).
za dużo php
5
Istnieje już wiele odpowiedzi. W rzeczywistości jest to singletonobiekt, w którym staticmetody są tylko funkcjami, byt nie będący jednostką organizacyjną.
fastcodejava 16.01.11
4
Zależy od wdrożenia .. csharpindepth.com/Articles/General/Singleton.aspx
VJAI
4
Istnieje różnica, gdy chcesz zezwolić stronom trzecim na dostarczenie implementacji klasy. W takim przypadku zwykle potrzebujesz również wzorów fabrycznych. Zobacz agiletribe.wordpress.com/2013/10/08/…
AgilePro
IMO ta odpowiedź bardzo dobrze podsumowuje stackoverflow.com/questions/14097656/…
Dave

Odpowiedzi:

1251

Co sprawia, że ​​mówisz, że metoda singletonowa lub statyczna nie jest bezpieczna dla wątków? Zwykle oba powinny być implementowane, aby były bezpieczne dla wątków.

Duża różnica między singletonem a garstką metod statycznych polega na tym, że singletony mogą implementować interfejsy (lub czerpać z użytecznych klas bazowych, choć z mojego doświadczenia jest to mniej powszechne), więc możesz ominąć singleton tak, jakby był „tylko kolejnym” " realizacja.

Jon Skeet
źródło
29
Cóż, jeśli wolisz, żadne z nich nie jest z natury bezpieczne dla wątków, musisz sprawić, aby były bezpieczne dla obu wątków, więc nie ma różnicy.
Jorge Córdoba
119
Czy możesz podać przykład czegoś, co z natury jest bezpieczne dla wątków, innego niż niezmienne typy?
Jon Skeet
26
Do Skeet: Ludzie, którzy twierdzą, że singleton nie jest bezpieczny dla wątków, oznaczają, że singleton jest niepotrzebnie dzielony między wątkami , podczas gdy obiekty stosu są udostępniane, kiedy jest to potrzebne, co oznacza, że ​​nie musisz wykonywać niepotrzebnej synchronizacji.
45
@Geek: Wyobraź sobie, że singleton implementuje interfejs Fooi masz metodę przyjmującą Foojako parametr. Przy takiej konfiguracji dzwoniący mogą wybrać użycie singletonu jako implementacji - lub mogą użyć innej implementacji. Metoda jest oddzielona od singletonu. Porównaj to z sytuacją, w której klasa ma tylko metody statyczne - każdy fragment kodu, który chce wywołać te metody, jest ściśle powiązany z klasą, ponieważ musi określić, która klasa zawiera metody statyczne.
Jon Skeet,
10
@AmirBareket: Nie jest to singleton według wzorca projektowego singleton - jeśli sama klasa pozwala na tworzenie wielu instancji, nie jest to singleton IMO, niezależnie od tego, co robi fabryka.
Jon Skeet,
475

Prawdą jest odpowiedź Jona Skeeta na innym forum tutaj .

Singleton umożliwia dostęp do jednej utworzonej instancji - ta instancja (a raczej odwołanie do tej instancji) może zostać przekazana jako parametr do innych metod i traktowana jak normalny obiekt.

Klasa statyczna dopuszcza tylko metody statyczne.

Kezzer
źródło
64
Dlaczego miałbyś przekazać Singleton jako parametr, jeśli możesz uzyskać dostęp do tego samego wystąpienia z dowolnego miejsca, wywołując metodę statyczną getInstance ()?
Henrique Ordine
23
@HenriqueOrdine Więc może zmieścić się w istniejącym kodzie i zapewnić interfejs?
6
@HenriqueOrdine Mówią o klasie statycznej, a nie klasie metodami statycznymi. Nie można utworzyć instancji klasy statycznej. Niemniej jednak, jeśli przekażesz instancję klasy (niestatycznej), która zawiera metody statyczne, nie możesz wywoływać metod statycznych w instancji.
Goran,
3
Co to jest klasa statyczna? Przynajmniej w Javie nie ma czegoś takiego.
Henrique Ordine,
16
@Goran Początkowo byłem bardzo zdezorientowany twoimi sformułowaniami. Powiedziałeś „nie możesz wywoływać metod statycznych w instancji”. Przeczytałem, że „jeśli masz odwołanie do obiektu instancji, nie możesz wywoływać żadnych statycznych metod, jakie może on mieć”. To oczywiście nieprawda. Po ponownym przeczytaniu go kilka razy myślę, że miałeś na myśli „z wewnątrz metod statycznych nie można uzyskać dostępu do obiektów niestatycznych w klasie”, co jest poprawne. Chcę wyjaśnić, że dla każdego, kto zna te pojęcia, spotka się z tą odpowiedzią i przeczyta twoje komentarze.
Andrew Steitz,
359
  1. Obiekty Singleton są przechowywane w Heap , ale obiekty statyczne są przechowywane w stosie .
  2. Możemy sklonować (jeśli projektant tego nie wyłączył) obiekt singletonu, ale nie możemy sklonować obiektu klasy statycznej.
  3. Klasy singletonowe są zgodne z OOP (obiektowymi zasadami), klasy statyczne nie.
  4. Możemy zaimplementować interfaceklasę Singleton, ale metody statyczne klasy (lub np. C # static class) nie mogą.
Vadluri Sreenu
źródło
99
Drugie stwierdzenie jest błędne. Nie możemy sklonować obiektu Singleton. Implementacja Singleton musi temu odmówić. Jeśli naprawdę możesz sklonować Singleton, to nie jest to Singleton.
Alexander Yancharuk
19
Ta odpowiedź jest niepoprawna dla Javy: ani singleton, ani statyczny nie używa stosu.
AgilePro,
72
# 1 nie jest ważny. # 2 opisuje wadliwą implementację. # 3 jest całkowicie nieuzasadniony.
Casey
31
Jak można przechowywać obiekty statyczne na stosie? Nowa ramka stosu jest tworzona po wywołaniu metody, przechowuje zmienne lokalne metody, ta ramka stosu jest usuwana, gdy metoda powraca, a te zmienne lokalne są tracone. Pewny stos jest szybki, ale nie nadaje się do przechowywania obiektów statycznych.
mike_m
23
Nie rozumiem liczby głosów pozytywnych na ten temat. 1) Dlaczego Singleton powinien być przechowywany na stosie? W językach zarządzanych, takich jak C # lub Java, dane są przechowywane na zarządzanej stercie, z wyjątkiem zmiennych / parametrów metody lokalnej. 2) Jeśli możesz go sklonować, to nie jest to poprawnie zaimplementowany singleton. 3) Singleton jest znany jako anty-wzór OOP; tzn. coś, czego powinieneś unikać, jeśli to możliwe. 4) To jedyna rzecz, która jest poprawna.
Groo
152

Wzorzec Singleton ma kilka zalet w stosunku do klas statycznych. Po pierwsze, singleton może rozszerzać klasy i implementować interfejsy, podczas gdy klasa statyczna nie może (może rozszerzać klas, ale nie dziedziczy członków ich instancji). Singleton może być inicjowany leniwie lub asynchronicznie, podczas gdy klasa statyczna jest generalnie inicjalizowana podczas pierwszego ładowania, co prowadzi do potencjalnych problemów z modułem ładującym klasy. Jednak najważniejszą zaletą jest to, że singletony można przetwarzać polimorficznie, nie zmuszając ich użytkowników do założenia, że ​​istnieje tylko jedna instancja.

neil.johnson
źródło
10
+1 za dobre, pragmatyczne punkty. Wzór singletonu jest ogólnie nadużywany, ale jest kilka sytuacji, w których jest on odpowiedni. Zobacz także: agiletribe.wordpress.com/2013/10/08/…
AgilePro
3
Masz rację, jeśli chodzi o zaletę bycia polimorficznym. To jest najważniejszy punkt
Ahmad
Zagnieżdżona klasa statyczna może implementować interfejs. Spróbuj go zakodować, zadziała. Mogę skompilować kod bez żadnego błędu.
nanosoft
75

staticklasy nie są dla niczego, co wymaga stanu. Jest to przydatne do łączenia wielu funkcji razem Math( tj. (Lub Utilsw projektach). Więc nazwa klasy daje nam jedynie wskazówkę, gdzie możemy znaleźć funkcje i nic więcej.

Singletonto mój ulubiony wzór i używam go do zarządzania czymś w jednym punkcie. Jest bardziej elastyczny niż staticklasy i może utrzymać swój stan. Może implementować interfejsy, dziedziczyć z innych klas i zezwalać na dziedziczenie.

Moja zasada wyboru między statici singleton:

Jeśli jest kilka funkcji, które powinny być trzymane razem, to staticjest wybór. Wszystko inne, co wymaga pojedynczego dostępu do niektórych zasobów, można zaimplementować jako singleton.

Xaqron
źródło
16
Dlaczego klasy statyczne nie powinny robić niczego, co wymaga zachowania stanu?
Trisped
12
@Trisped: Nie masz precyzyjnej kontroli nad inicjalizacją ani finalizacją.
Xaqron
7
zgubiłeś mnie na „Singleton to mój ulubiony wzór”. Singleton jest tak ostrym zakrętem, że należy go traktować zarówno jako anty-wzór, jak i wzór. Klasy mogą również mieć stany statyczne, to jest również pojedynczy dostęp, jeśli cokolwiek stan statyczny jest bardziej „pojedynczy dostęp” niż singletony, ponieważ większość implementacji singletonów jest zepsuta, tj. możesz sklonować singletona, podczas gdy statyczny jest błogosławiony przez definicję unikalności.
PoweredByRice
1
Co to znaczy utrzymać stan? Co to jest stan?
Kyle Delaney
2
@KyleDelaney: Po prostu Statejest kombinacją różnych właściwości obiektu, które zwykle zmieniają się w czasie. Możesz Google formalnie zdefiniować.
Xaqron
65

Klasa statyczna: -

  1. Nie można utworzyć wystąpienia klasy statycznej.

  2. Ładowane automatycznie przez środowisko uruchomieniowe języka wspólnego (CLR) .NET Framework po załadowaniu programu lub przestrzeni nazw zawierającej klasę.

  3. Klasa statyczna nie może mieć konstruktora.

  4. Nie możemy przekazać klasy statycznej do metody.

  5. Nie możemy dziedziczyć klasy statycznej na inną klasę statyczną w języku C #.

  6. Klasa posiadająca wszystkie metody statyczne.

  7. Lepsza wydajność (metody statyczne są powiązane w czasie kompilacji)

Singel:-

  1. Możesz utworzyć jedną instancję obiektu i użyć go ponownie.

  2. Instancja Singleton jest tworzona po raz pierwszy na żądanie użytkownika.

  3. Klasa Singleton może mieć konstruktor.

  4. Możesz utworzyć obiekt klasy singleton i przekazać go do metody.

  5. Klasa Singleton nie mówi o żadnym ograniczeniu dziedziczenia.

  6. Możemy pozbyć się obiektów klasy singleton, ale nie klasy statycznej.

  7. Metody można zastąpić.

  8. Może być ładowany leniwie, gdy jest to potrzebne (klasy statyczne są zawsze ładowane)

  9. Możemy zaimplementować interfejs (klasa statyczna nie może zaimplementować interfejsu).

RajeshVerma
źródło
13
Klasy statyczne mają konstruktory: msdn.microsoft.com/en-us/library/k9x6w0hc.aspx
Tomer Arazy
2
Tak, statyczny może mieć konstruktor wewnętrzny dla tej klasy. Jest to wywoływane, gdy wywoływana jest dowolna metoda statyczna w klasie.
rahulmr
W przypadku singletonu w czasie kompilacji jest on zapisywany w pamięci HEAP, ale jeśli zostanie utworzony natychmiast, czy zostanie zapisany w STOSOWANIU?
Luminous_Dev
@Luminous_Dev Nie. Każda instancja singletona jest instancją obiektu na koniec dnia. Bez wątpienia będzie przechowywany na stosie.
RBT
1
@rahulmr Ważne rozróżnienie: konstruktor jest również wywoływany przed utworzeniem pierwszej instancji (tylko AKA).
CoolOppo
53

Klasa statyczna to taka, która ma tylko metody statyczne, dla których lepszym słowem byłyby „funkcje”. Styl projektowania zawarty w klasie statycznej jest czysto proceduralny.

Singleton jest natomiast wzorem charakterystycznym dla projektu OO. Jest to instancja obiektu (ze wszystkimi związanymi z tym możliwościami, takimi jak polimorfizm), z procedurą tworzenia, która zapewnia, że ​​istnieje tylko jedna instancja tej konkretnej roli przez cały okres jej istnienia.

Morendil
źródło
1
polimorfizm w ogóle nie wchodzi w grę z singletonami
32
Więc uważasz. Myślę inaczej. ;) Na przykład wyobraź sobie fabrykę singletonów, która zwraca interfejs. Wiesz, że dostajesz ISingleton (i to na zawsze taki sam), ale niekoniecznie która implementacja.
Morendil,
Zagnieżdżona klasa statyczna może również mieć metody instancji, nie jest ograniczona do posiadania tylko metod statycznych. Koduj i widać.
nanosoft
W językach z ładniejszym modelem obiektowym (np. Ruby) klasy również są obiektami. „Czysto proceduralny” aspekt klasy statycznej jest arbitralnym ograniczeniem narzuconym przez język.
Max
36

We wzorze singletonu możesz utworzyć singleton jako instancję typu pochodnego, nie możesz tego zrobić z klasą statyczną.

Szybki przykład:

if( useD3D )
    IRenderer::instance = new D3DRenderer
else
    IRenderer::instance = new OpenGLRenderer
Don Neufeld
źródło
39
To nie jest tak naprawdę singleton, dla mnie wygląda bardziej jak fabryka.
vava
10
Niezupełnie podstawowa różnica między nimi polega na tym, że Singleton „buforuje” swój pojedynczy obiekt i zwraca (odwołuje się) ten sam obiekt. Wzorzec fabryczny utworzy nowe wystąpienia.
Mystic
12
Potem jest proxy-singleton :)
vava
3
Hmm, znam tę odmianę Singleton jako MonoState.
Huppie
przykładem jest wzór fabryczny
Rajavel D
26

Aby rozwinąć odpowiedź Jona Skeeta

Duża różnica między singletonem a garstką metod statycznych polega na tym, że singletony mogą implementować interfejsy (lub czerpać z użytecznych klas bazowych, chociaż jest to mniej powszechny edytor IME), dzięki czemu można ominąć singleton tak, jakby był „tylko kolejną” implementacją.

Singletony są łatwiejsze w pracy, gdy jednostka testuje klasę. Za każdym razem, gdy przekazujesz singletony jako parametr (konstruktory, setery lub metody), możesz zamiast tego zastąpić fałszywą lub skrótową wersję singletonu.

Mike Rylander
źródło
Nie sądzę, że możesz bezpośrednio wyśmiewać singletona. Czy nie musiałbyś zadeklarować interfejsu, który implementują zarówno singleton, jak i próbna klasa?
Ellen Spertus
@espertus Dlaczego nie możesz kpić z singletona? Przykład użycia mockito MySingleton mockOfMySingleton = mock(MySingleton.class).
Mike Rylander
masz rację, możesz wyśmiewać to za pomocą narzędzi takich jak mockito, które używają odbicia. Chodziło mi o to, że nie można wyśmiewać go bezpośrednio, dzieląc go na klasy i zastępując jego metody.
Ellen Spertus
@espertus Dlaczego nie? Kiedy tworzysz instancję testowanego obiektu, możesz zastąpić implementację podklasy swojego singletona wszędzie tam, gdzie używałbyś oryginału. Np .:new ClazzToTest(mockSingleton);
Mike Rylander
Nie korzystałem z Mockito, ale jak możesz podklasować klasę, która ma prywatnego konstruktora, co ma miejsce w przypadku singletonów, z wyjątkiem użycia refleksji? Powiązane dyskusje: stackoverflow.com/questions/2302179/mocking-a-singleton-class stackoverflow.com/questions/15939023/...
Ellen Spertus
23

Oto dobry artykuł: http://javarevisited.blogspot.com.au/2013/03/difference-between-singleton-pattern-vs-static-class-java.html

Klasy statyczne

  • klasa posiadająca wszystkie metody statyczne .
  • lepsza wydajność (metody statyczne są powiązane w czasie kompilacji)
  • nie może przesłonić metod, ale może używać ukrywania metod. ( Co to jest metoda ukrywania w Javie? Nawet wyjaśnienie JavaDoc jest mylące )

    public class Animal {
        public static void foo() {
            System.out.println("Animal");
        }
    }
    
    public class Cat extends Animal {
        public static void foo() {  // hides Animal.foo()
            System.out.println("Cat");
        }
    }
    

Singel

Podsumowując, używałbym klas statycznych tylko do przechowywania metod util i używania Singleton do wszystkiego innego.


Edycje

JackDev
źródło
4
Nie wiem o Javie, ale w .Net twoje dwa ostatnie punkty są niepoprawne. Klasy statyczne mogą odwoływać się do właściwości statycznych i pól, więc pod warunkiem, że są one równe. I są ładowane z opóźnieniem - konstruktor statyczny jest uruchamiany, gdy: 1) Utworzona jest instancja klasy. 2) Odwołanie do dowolnego statycznego elementu klasy. 1 nie ma zastosowania, co pozostawia 2. Tak więc klasa statyczna nie jest ładowana aż do pierwszego użycia.
jmoreno
1
W przypadku klasy statycznej, chociaż nie można przesłonić metody statycznej, można ukryć metodę statyczną przed jej rodzica.
Max Peng,
jeśli Animal animal = new Cat();potem animal.foo();co się dzieje?
Luminous_Dev
@jmoreno klasa statyczna nie jest ładowana do pierwszego użycia? Wierzę, że jest przechowywany w pamięci stosu w czasie kompilacji. I jest natychmiast dostępny ... prawda?
Luminous_Dev
@Luminous_Dev: przynajmniej dla .net klasa statyczna ma konstruktor, który działa przy pierwszym dostępie, więc nie, nie jest ona natychmiast dostępna. Konstruktor statyczny może teoretycznie zająć nieograniczoną ilość czasu. Gdzie jest przechowywana (lub jakakolwiek inna klasa) jest szczegółem implementacji, nie jest to tak naprawdę istotne dla tego pytania.
jmoreno
22

Kolejną zaletą singletona jest to, że można go łatwo serializować, co może być konieczne, jeśli trzeba zapisać jego stan na dysku lub wysłać go gdzieś zdalnie.

Alex
źródło
19

Nie jestem wielkim teoretykiem OO, ale z tego co wiem, myślę, że jedyną cechą OO, której brakuje klas statycznych w porównaniu do Singletonów, jest polimorfizm. Ale jeśli go nie potrzebujesz, dzięki statycznej klasie możesz oczywiście dziedziczyć (nie jestem pewien co do implementacji interfejsu) oraz hermetyzować dane i funkcje.

Komentarz Morendila: „Styl projektowania ujęty w klasie statycznej jest czysto proceduralny” Mogę się mylić, ale się nie zgadzam. W metodach statycznych można uzyskać dostęp do elementów statycznych, które byłyby dokładnie takie same, jak metody singletonowe uzyskujące dostęp do elementów pojedynczej instancji.

edytuj:
Właściwie myślę teraz, że inną różnicą jest to, że klasa Statyczna jest tworzona przy starcie programu * i żyje przez cały okres życia programu, podczas gdy singleton jest wyraźnie tworzony w pewnym momencie i również może zostać zniszczony.

* lub może wystąpić przy pierwszym użyciu, zależnie od języka, tak myślę.

Petruza
źródło
15
Tak, wydaje się, że wszyscy inni ignorują fakt, że klasa z metodami statycznymi może mieć również prywatne pola statyczne, których może nadal używać do utrzymywania stanu (i wystawiać niektóre z nich na kod klienta za pośrednictwem publicznych ustawień statycznych / getterów).
user289463,
17

Aby zilustrować punkt Jona, co pokazano poniżej, nie można tego zrobić, jeśli Logger był klasą statyczną. Klasa SomeClassoczekuje, że instancja ILoggerimplementacji zostanie przekazana do jej konstruktora.

Klasa Singleton jest ważna, aby możliwe było wstrzyknięcie zależności.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {

            var someClass = new SomeClass(Logger.GetLogger());
        }


    }

    public class SomeClass 
    {
        public SomeClass(ILogger MyLogger)
        {

        }
    }

    public class Logger : ILogger
    {
        private static Logger _logger;
        private Logger() { }

        public static Logger GetLogger()
        {
            if (_logger==null)
            {
                _logger = new Logger();
            }

            return _logger;
        }

        public void Log()
        {

        }

    }


    public interface ILogger
    {
         void Log();
    }
}
developer747
źródło
13

Cóż, singleton jest zwykłą klasą, która jest instowana, ale tylko raz i pośrednio z kodu klienta. Klasa statyczna nie jest tworzona. O ile wiem metody statyczne (klasa statyczna musi mieć metody statyczne) są szybsze niż metody niestatyczne.

Edycja:
FxCop Opis reguły wydajności: „Metody, które nie uzyskują dostępu do danych instancji lub metod instancji wywołania, mogą być oznaczone jako statyczne (współużytkowane w VB). Po wykonaniu tej czynności kompilator wyśle ​​do tych członków nie wirtualne witryny wywołujące, co zapobiegnie sprawdzanie w czasie wykonywania każdego wywołania, które zapewnia, że ​​bieżący wskaźnik obiektu nie ma wartości zerowej. Może to spowodować wymierny wzrost wydajności kodu wrażliwego na wydajność. W niektórych przypadkach brak dostępu do bieżącej instancji obiektu oznacza problem z poprawnością. ”
Nie wiem, czy dotyczy to również metod statycznych w klasach statycznych.

agnieszka
źródło
11

Instancje Singletona są tworzone, to tylko jedna instancja kiedykolwiek stworzona, stąd singiel w Singleton.

Klasa statyczna nie może być utworzona przez nic innego niż siebie.

Kezzer
źródło
Klasa statyczna może być bardzo często tworzona w Javie. Przeczytaj docs.oracle.com/javase/tutorial/java/javaOO/nested.html.
Zapoznaj się
8

Główne różnice to:

  • Singleton ma instancję / obiekt, podczas gdy klasa statyczna jest zbiorem metod statycznych
  • Singleton można przedłużyć np. Przez interfejs, podczas gdy klasa statyczna nie może.
  • Singleton może być dziedziczony, co obsługuje zasady otwierania / zamykania w zasadach SOLID, z drugiej strony klasy statycznej nie można dziedziczyć i musimy wprowadzać zmiany w sobie.
  • Obiekt Singleton można przekazać do metod, podczas gdy klasa statyczna, ponieważ nie ma instancji, nie może zostać przekazana jako parametry
Faran Shabbir
źródło
7

Singleton jest lepszym podejściem z perspektywy testowania. W przeciwieństwie do klas statycznych, singleton może implementować interfejsy i można użyć próbnej instancji i wstrzyknąć je.

W poniższym przykładzie zilustruję to. Załóżmy, że masz metodę isGoodPrice (), która używa metody getPrice () i implementujesz getPrice () jako metodę w singletonie.

singleton zapewniający funkcjonalność getPrice:

public class SupportedVersionSingelton {

    private static ICalculator instance = null;

    private SupportedVersionSingelton(){

    }

    public static ICalculator getInstance(){
        if(instance == null){
            instance = new SupportedVersionSingelton();
        }

        return instance;
    }

    @Override
    public int getPrice() {
        // calculate price logic here
        return 0;
    }
}

Korzystanie z getPrice:

public class Advisor {

    public boolean isGoodDeal(){

        boolean isGoodDeal = false;
        ICalculator supportedVersion = SupportedVersionSingelton.getInstance();
        int price = supportedVersion.getPrice();

        // logic to determine if price is a good deal.
        if(price < 5){
            isGoodDeal = true;
        }

        return isGoodDeal;
    }
}


In case you would like to test the method isGoodPrice , with mocking the getPrice() method you could do it by:
Make your singleton implement an interface and inject it. 



  public interface ICalculator {
        int getPrice();
    }

Ostateczne wdrożenie Singleton:

public class SupportedVersionSingelton implements ICalculator {

    private static ICalculator instance = null;

    private SupportedVersionSingelton(){

    }

    public static ICalculator getInstance(){
        if(instance == null){
            instance = new SupportedVersionSingelton();
        }

        return instance;
    }

    @Override
    public int getPrice() {
        return 0;
    }

    // for testing purpose
    public static void setInstance(ICalculator mockObject){
        if(instance != null ){
instance = mockObject;
    }

klasa testowa:

public class TestCalculation {

    class SupportedVersionDouble implements ICalculator{
        @Override
        public int getPrice() { 
            return 1;
        }   
    }
    @Before
    public void setUp() throws Exception {
        ICalculator supportedVersionDouble = new SupportedVersionDouble();
        SupportedVersionSingelton.setInstance(supportedVersionDouble);

    }

    @Test
    public void test() {
          Advisor advidor = new Advisor();
          boolean isGoodDeal = advidor.isGoodDeal();
          Assert.assertEquals(isGoodDeal, true);

    }

}

W przypadku, gdy skorzystamy z alternatywnej metody statycznej do implementacji metody getPrice (), trudno było naśladować metodę getPrice (). Można kpić z elektryczności statycznej, ale nie wszystkie produkty mogą z niego korzystać.

Amir Bareket
źródło
1
To nie jest teraz bezpieczne dla wątków i ogólnie nieprzyjemne pod względem dostępu do implementacji interfejsu. Jasne, posiadanie interfejsu jest dobre dla testowalności - ale po co więc męczyć się z singletonem? Po prostu unikaj singletona; mieć jedną klasę implementującą ją do celów produkcyjnych, jedną implementację do celów testowych i wstrzyknąć odpowiednią instancję w zależności od tego, co robisz. W ogóle nie trzeba łączyć singletona z dzwoniącymi.
Jon Skeet
Dzięki za opinie. bardzo łatwo jest zapewnić bezpieczeństwo wątku. ponadto używam singletonu do buforowania.
Amir Bareket
1
Tak, choć bez sensu. Ponownie, po prostu łatwiej jest nie używać singletona.
Jon Skeet
6

Zgadzam się z tą definicją:

Słowo „ singiel ” oznacza pojedynczy obiekt w całym cyklu życia aplikacji, więc zakres jest na poziomie aplikacji.

statyczne nie ma żadnego wskaźnika Object, więc zakres jest na poziomie App Domain.

Ponadto oba należy wdrożyć, aby były bezpieczne dla wątków.

Można znaleźć inne interesujące różnice dotyczące: Wzorca singletonu a klasy statycznej

Alessandro Ornano
źródło
5

Jedną zauważalną różnicą jest różna instancja, która pochodzi z Singletonów.

W przypadku klas statycznych jest on tworzony przez CLR i nie mamy nad nim kontroli. w przypadku singletonów obiekt jest tworzony w pierwszej instancji, do której próbowano uzyskać dostęp.

Eranga Dissanayaka
źródło
4

W wielu przypadkach te dwa nie mają praktycznej różnicy, szczególnie jeśli instancja singletonu nigdy się nie zmienia lub zmienia bardzo powoli, np. Konfiguracje utrzymywania.

Powiedziałbym, że największą różnicą jest to, że singleton jest nadal normalną Java Bean, w przeciwieństwie do wyspecjalizowanej klasy Java tylko statycznej. Z tego powodu singleton jest akceptowany w wielu innych sytuacjach; w rzeczywistości jest to domyślna strategia tworzenia instancji Spring Framework. Konsument może, ale nie musi wiedzieć, że jest to singleton przekazywany dookoła, po prostu traktuje to jak zwykłą fasolę Java. Jeśli zmieniają się wymagania, a singleton zamiast tego musi stać się prototypem, jak to często widzimy na wiosnę, można to zrobić całkowicie bezproblemowo, bez zmiany linii kodu dla konsumenta.

Ktoś inny wspomniał wcześniej, że klasa statyczna powinna mieć charakter czysto proceduralny, np. Java.lang.Math. Moim zdaniem, taka klasa nigdy nie powinna być przekazywana i nigdy nie powinna przyjmować niczego innego jak statyczny finał jako atrybuty. Do wszystkiego innego użyj singletona, ponieważ jest on znacznie bardziej elastyczny i łatwiejszy w utrzymaniu.

Chris
źródło
4

Dysponujemy strukturą DB, która zapewnia połączenia z zapleczem. Aby uniknąć brudnych odczytów u wielu użytkowników, użyliśmy wzorca singletonu, aby zapewnić dostępność pojedynczej instancji w dowolnym momencie.

W c # klasa statyczna nie może implementować interfejsu. Kiedy klasa pojedynczej instancji musi zaimplementować interfejs dla umów biznesowych lub celów IoC, tutaj używam wzorca Singleton bez klasy statycznej

Singleton zapewnia sposób na utrzymanie stanu w scenariuszach bezstanowych

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

RK_Muddala
źródło
3
  1. Powolne ładowanie
  2. Obsługa interfejsów, dzięki czemu można zapewnić osobną implementację
  3. Możliwość zwrotu typu pochodnego (jako połączenie lazyloadingu i implementacji interfejsu)
Tilak
źródło
Zagnieżdżona klasa statyczna może bardzo zaimplementować interfejs w Javie. Twój drugi punkt jest błędny.
nanosoft
3

za. Serializacja - członkowie statyczni należą do klasy i dlatego nie można ich serializować.

b. Chociaż ustawiliśmy konstruktor jako prywatny, statyczne zmienne składowe nadal będą przenoszone do podklasy.

do. Nie możemy wykonać leniwej inicjalizacji, ponieważ wszystko zostanie załadowane tylko podczas ładowania klasy.

Vivek Vermani
źródło
3

Z perspektywy klienta zachowanie statyczne jest znane klientowi, ale zachowanie Singleton można wykonać ukryte przed klientem. Klient może nigdy nie wiedzieć, że jest tylko jedna instancja, z którą wciąż się bawi.

Arpit Khandelwal
źródło
3

Przeczytałem następujące i myślę, że to też ma sens:

Dbanie o interesy

Pamiętaj, że jedną z najważniejszych zasad OO jest to, że obiekt jest odpowiedzialny za siebie. Oznacza to, że problemy związane z cyklem życia klasy powinny być rozwiązywane w klasie, a nie delegowane do konstrukcji językowych, takich jak statyczne i tak dalej.

z książki Objected-Oriented Thought Process 4th Ed.

niepolarność
źródło
Nie zgodziłbym się, ponieważ to naprawdę dodaje odpowiedzialność klasie, co (zakładając, że coś robi) oznacza, że ​​obecnie narusza zasadę pojedynczej odpowiedzialności.
ssmith
3

W artykule, który napisałem, opisałem swój punkt widzenia na temat tego, dlaczego singleton jest znacznie lepszy niż klasa statyczna:

  1. Klasa statyczna nie jest w rzeczywistości klasą kanoniczną - jest to przestrzeń nazw z funkcjami i zmiennymi
  2. Używanie klasy statycznej nie jest dobrą praktyką ze względu na łamanie zasad programowania obiektowego
  3. Klasa statyczna nie może być przekazana jako parametr dla innych
  4. Klasa statyczna nie nadaje się do „leniwej” inicjalizacji
  5. Inicjalizacja i użycie klasy statycznej jest zawsze trudne
  6. Wdrożenie zarządzania wątkami jest trudne
Paul R.
źródło
Poprawiłbym gramatykę angielską, ale poza tym jest to interesująca lektura :)
Noctis
3
  1. Możemy stworzyć obiekt klasy singleton i przekazać go do metody.

  2. Klasa Singleton nie ma żadnych ograniczeń dziedziczenia.

  3. Nie możemy pozbywać się obiektów klasy statycznej, ale możemy singletonować.

Sanjay Dwivedi
źródło
Jaki jest pożytek z przekazania singletona do metody, jeśli zawsze jest tylko jedna, a ta zawsze ma odniesienie statyczne?
Aaron Franke,
3

Odróżnienie od klasy statycznej

JDK ma przykłady zarówno singletonu, jak i static, z jednej strony java.lang.Mathjest klasą końcową z metodami static, z drugiej stronyjava.lang.Runtime jest klasą singleton.

Zalety singletonu

  • Jeśli potrzeba utrzymania stanu niż wzorca singletonu jest lepszym wyborem niż klasa statyczna, ponieważ utrzymanie stanu w klasie statycznej prowadzi do błędów, szczególnie w środowisku współbieżnym, które mogą prowadzić do warunków wyścigu bez odpowiedniej równoległej modyfikacji synchronizacji przez wiele wątków.

  • Klasa Singleton może być leniwie ładowana, jeśli jest ciężkim obiektem, ale klasa statyczna nie ma takich zalet i zawsze chętnie się ładuje.

  • Dzięki singletonowi możesz wykorzystać dziedziczenie i polimorfizm, aby rozszerzyć klasę bazową, zaimplementować interfejs i zapewnić różne implementacje.

  • Ponieważ metod statycznych w Javie nie można zastąpić, prowadzą one do nieelastyczności. Z drugiej strony możesz przesłonić metody zdefiniowane w klasie singleton, rozszerzając ją.

Wady klasy statycznej

  • Łatwiej jest napisać test jednostkowy dla singletonu niż klasy statycznej, ponieważ można przekazać próbny obiekt, ilekroć oczekiwany jest singleton.

Zalety klasy statycznej

  • Klasa statyczna zapewnia lepszą wydajność niż singleton, ponieważ metody statyczne są powiązane w czasie kompilacji.

Istnieje kilka realizacji wzoru singletonu, z których każdy ma zalety i wady.

  • Chętnie ładuje singletona
  • Podwójnie sprawdzony singleton blokujący
  • Idiom posiadacza inicjalizacji na żądanie
  • Singleton oparty na wyliczeniu

Szczegółowy opis każdego z nich jest zbyt szczegółowy, więc po prostu umieszczam link do dobrego artykułu - Wszystko, co chcesz wiedzieć o Singleton

Oleg Poltoratskii
źródło
2

Istnieje ogromna różnica między pojedynczym wystąpieniem klasy statycznej (to znaczy pojedynczym wystąpieniem klasy, która okazuje się zmienną statyczną lub globalną) a pojedynczym wskaźnikiem statycznym do wystąpienia klasy na stercie:

Po zamknięciu aplikacji zostanie wywołany destruktor instancji klasy statycznej. Oznacza to, że jeśli użyłeś tego statycznego wystąpienia jako singletonu, twój singleton przestanie działać poprawnie. Jeśli nadal działa kod korzystający z tego singletonu, na przykład w innym wątku, kod może ulec awarii.

gnasher729
źródło
1
Więc jeśli aplikacja wyjdzie, czy Singleton nadal pozostanie w pamięci?
nanosoft
Myślę, że masz na myśli, kiedy kończy się bieżący wątek, a nie aplikacja, prawda? Jeśli aplikacja zostanie zamknięta, żaden wątek nie będzie mógł z niej korzystać.
Tom Brito
2

Różnica w mojej głowie polega na wdrażaniu programowania obiektowego (Singleton / Prototype) lub programowania funkcjonalnego (Static).

Jesteśmy zbyt skupieni na liczbie obiektów utworzonych przez wzorzec singletonu, kiedy powinniśmy się skupić na tym, że w końcu trzymamy obiekt. Jak inni już powiedzieli, można go rozszerzyć, przekazać jako parametr, ale co najważniejsze, jest on pełny.

Z drugiej strony statyczny służy do implementacji programowania funkcjonalnego. Elementy statyczne należą do klasy. Są bezpaństwowcami.

Nawiasem mówiąc, czy wiesz, że możesz tworzyć pojedyncze klasy statyczne :)

Atif Karbelkar
źródło
Jaki jest sens przekazywania singletonu jako parametru, ponieważ zawsze ma on statyczne odwołanie do klasy?
Aaron Franke,