Singleton: jak należy go stosować

Edytuj: Z innego pytania podałem odpowiedź, która zawiera linki do wielu pytań / odpowiedzi na temat singletonów: Więcej informacji o singletonach tutaj:

Więc przeczytałem wątek Singletons: dobry projekt czy kula?
A kłótnia wciąż szaleje.

Widzę Singletony jako wzorzec projektowy (dobry i zły).

Problem z Singletonem to nie Wzór ale raczej użytkownicy (sorry wszystkim). Wszyscy i ich ojciec myślą, że mogą wdrożyć jeden poprawnie (i z wielu wywiadów, które zrobiłem, większość ludzi nie może). Również dlatego, że wszyscy myślą, że mogą zaimplementować poprawny Singleton, nadużywają wzorca i używają go w sytuacjach, które nie są odpowiednie (zastępowanie zmiennych globalnych Singletonami!).

Więc główne pytania, na które należy odpowiedzieć to:

  • Kiedy należy stosować Singleton
  • Jak poprawnie zaimplementować Singleton

Mam nadzieję, że ten artykuł pozwoli nam Zbierz razem w jednym miejscu (zamiast google i przeszukiwać wiele witryn) autorytatywne źródło, kiedy (i jak) prawidłowo używać Singletona. Odpowiednia byłaby również lista anty-zastosowań i wspólnych złych implementacji wyjaśniających, dlaczego nie działają, a dla dobrych implementacji ich słabości.


Więc weź się w garść:
Podniosę rękę i powiem, że to jest to, czego używam, ale prawdopodobnie ma problemy.
Lubię" Scotta Myersa" z przedmiotu w jego książkach "efektywne C++"

Dobre sytuacje do używania singletonów (niewiele):

  • ramy logowania
  • thread recycling pools
/*
 * C++ Singleton
 * Limitation: Single Threaded Design
 * See: http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
 *      For problems associated with locking in multi threaded applications
 *
 * Limitation:
 * If you use this Singleton (A) within a destructor of another Singleton (B)
 * This Singleton (A) must be fully constructed before the constructor of (B)
 * is called.
 */
class MySingleton
{
    private:
        // Private Constructor
        MySingleton();
        // Stop the compiler generating methods of copy the object
        MySingleton(MySingleton const& copy);            // Not Implemented
        MySingleton& operator=(MySingleton const& copy); // Not Implemented

    public:
        static MySingleton& getInstance()
        {
            // The only instance
            // Guaranteed to be lazy initialized
            // Guaranteed that it will be destroyed correctly
            static MySingleton instance;
            return instance;
        }
};
OK. Pozwala uzyskać krytykę i inne wdrożenia razem.
:-)
Author: Loki Astari, 2008-09-17

24 answers

Wszyscy się mylicie. Przeczytaj pytanie. Odpowiedź:

Użyj Singletonu Jeśli:

  • musisz mieć tylko jeden obiekt typu w systemie

Nie używaj Singletonu, Jeśli:

  • chcesz zapisać pamięć
  • Chcesz spróbować czegoś nowego]}
  • chcesz pokazać ile wiesz
  • ponieważ wszyscy inni to robią (zobacz w Wikipedii)
  • w widżetach interfejsu użytkownika
  • to ma be a cache
  • w ciągach
  • W Sesjach
  • I can go all day long

Jak stworzyć najlepszy singleton:

    Im mniejszy, tym lepszy. Jestem minimalistą
  • Upewnij się, że jest bezpieczny dla wątku
  • Upewnij się, że nigdy nie jest null
  • Upewnij się, że jest utworzony tylko raz
  • Leniwa czy inicjalizacja systemu? Do Twoich wymagań
  • czasami system operacyjny lub JVM tworzy dla Ciebie singletony (np. w Javie każda definicja klasy jest singleton)
  • dostarczyć Destruktor lub jakoś wymyślić, jak pozbyć się zasobów
  • użyj małej pamięci
 161
Author: Javaxpert,
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-06-19 06:36:04

Singletony dają Ci możliwość łączenia dwóch złych cech w jednej klasie. To jest złe pod każdym względem.

Singleton daje:

  1. globalny dostęp do obiektu, oraz
  2. gwarancja, że nie można utworzyć więcej niż jednego obiektu tego typu
Numer jeden jest prosty. Globale są generalnie złe. Nigdy nie powinniśmy udostępniać obiektów na całym świecie, chyba że naprawdę tego potrzebujemy.

Numer dwa może brzmieć jak to ma sens, ale pomyślmy o tym. Kiedy ostatnio przypadkowo stworzyłeś nowy obiekt zamiast odwoływać się do istniejącego? Ponieważ jest to oznaczone C++, użyjmy przykładu z tego języka. Czy często przypadkowo piszesz

std::ostream os;
os << "hello world\n";

Kiedy zamierzałeś napisać

std::cout << "hello world\n";
Oczywiście, że nie. Nie potrzebujemy ochrony przed tym błędem, ponieważ tego rodzaju błąd po prostu się nie zdarza. Jeśli tak, prawidłową odpowiedzią jest pójście do domu i spanie przez 12-20 godzin i nadzieja czujesz się lepiej.

Jeśli potrzebny jest tylko jeden obiekt, po prostu utwórz jedną instancję. Jeśli jeden obiekt ma być globalnie dostępny, uczyń go globalnym. Ale to nie znaczy, że nie powinno być możliwe tworzenie innych jego instancji.

Ograniczenie "tylko jedna instancja jest możliwa" tak naprawdę nie chroni nas przed prawdopodobnymi błędami. Ale to sprawia, że nasz kod jest bardzo trudny do refaktoryzacji i utrzymania. Ponieważ dość często dowiadujemy się później , że potrzebujemy więcej niż jednej instancji. My do mamy więcej niż jedną bazę danych, my do mamy więcej niż jeden obiekt konfiguracyjny, chcemy kilka loggerów. Nasze testy jednostkowe mogą chcieć tworzyć i odtwarzać te obiekty przy każdym teście, aby wziąć wspólny przykład.

Więc singleton powinien być używany wtedy i tylko wtedy, gdy potrzebujemyzarówno cech, które oferuje: jeśli potrzebujemy globalnego dostępu (co jest rzadkie, ponieważ globale są ogólnie zniechęcane) i potrzebujemy aby zapobiec komukolwiek z ever tworzenie więcej niż jednej instancji klasy(co dla mnie brzmi jak kwestia projektowania). Jedynym powodem, dla którego widzę to jest to, że utworzenie dwóch instancji uszkodziłoby nasz stan aplikacji-prawdopodobnie dlatego, że klasa zawiera pewną liczbę statycznych członków lub podobną głupotę. W takim przypadku oczywistą odpowiedzią jest naprawienie tej klasy. To nie powinno zależeć od bycia jedynym przypadkiem.

Jeśli potrzebujesz globalnego dostępu do obiektu, zrób z niego globalny, jak std::cout. Ale nie ograniczaj liczba instancji, które można utworzyć.

Jeśli absolutnie, pozytywnie musisz ograniczyć liczbę instancji klasy do jednej i nie ma możliwości, aby tworzenie drugiej instancji mogło być obsługiwane bezpiecznie, to Wymuś to. Ale nie udostępniaj go również na całym świecie.

Jeśli potrzebujesz obu cech, to 1) Zrób singleton, i 2) daj mi znać, do czego ci to potrzebne, bo ciężko mi sobie wyobrazić taki przypadek.

 64
Author: jalf,
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
2016-01-07 09:46:53

Problem z singletonami nie jest ich implementacją. Chodzi o to, że łączą one dwie różne koncepcje, z których żadna nie jest oczywiście pożądana.

1) Singletony zapewniają globalny mechanizm dostępu do obiektu. Chociaż mogą one być marginalnie bardziej bezpieczne dla wątków lub marginalnie bardziej niezawodne w językach bez dobrze zdefiniowanego porządku inicjalizacji, to użycie to nadal jest moralnym odpowiednikiem zmiennej globalnej. To zmienna globalna ubrana w jakąś niezręczną składnię (Foo:: get_instance() zamiast g_foo, powiedzmy), ale służy dokładnie temu samemu celowi (pojedynczy obiekt dostępny w całym programie) i ma dokładnie te same wady.

2) Singletony zapobiegają wielokrotnym instancjom klasy. To rzadkość, IME, że tego rodzaju cechy powinny być pieczone w klasie. Zwykle jest to rzecz o wiele bardziej kontekstowa; wiele rzeczy, które są uważane za jedno-i-tylko-jedno, jest tak naprawdę po prostu zdarza się-być-tylko-jednym. IMO bardziej odpowiednim rozwiązaniem jest Utwórz tylko jedną instancję-dopóki nie zdasz sobie sprawy, że potrzebujesz więcej niż jednej instancji.

 35
Author: DrPizza,
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-09-17 19:27:56

Jedna rzecz ze wzorami: nie uogólniaj . Mają wszystkie przypadki, kiedy są użyteczne i kiedy zawodzą.

Singleton może być paskudny, gdy trzeba przetestować Kod. Zazwyczaj utknąłeś z jedną instancją klasy i możesz wybrać między otwarciem drzwi w konstruktorze lub jakąś metodą resetowania stanu i tak dalej.

Inny problem polega na tym, że Singleton w rzeczywistości jest niczym więcej niż zmienną globalną w ukryciu. Gdy masz za dużo globalny wspólny stan w twoim programie, sprawy mają tendencję do powrotu, wszyscy o tym wiemy.

Może to utrudnić śledzenie zależności . Gdy wszystko zależy od Singletonu, trudniej go zmienić, podzielić na dwa itp. Zazwyczaj się z tym trzymasz. Utrudnia to również elastyczność. Zbadaj pewien framework Dependency Injection , aby spróbować złagodzić ten problem.

 25
Author: Paweł Hajdan,
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-09-17 19:26:48

Singletony zasadniczo pozwalają mieć złożony stan Globalny w językach, które w przeciwnym razie utrudniają lub uniemożliwiają posiadanie złożonych zmiennych globalnych.

Java w szczególności używa singletonów jako zamiennika zmiennych globalnych, ponieważ wszystko musi być zawarte w klasie. Najbliżej zmiennych globalnych są publiczne zmienne statyczne, które mogą być używane tak, jakby były globalne z import static

C++ ma zmienne globalne, ale kolejność w jakiej konstruktory wywołane zmienne klasy globalnej są niezdefiniowane. W związku z tym singleton pozwala odroczyć utworzenie zmiennej globalnej do czasu, gdy ta zmienna jest potrzebna po raz pierwszy.

Języki takie jak Python i Ruby używają singletonów bardzo mało, ponieważ można używać zmiennych globalnych w module.

Kiedy więc dobrze/źle jest używać Singletona? Prawie dokładnie wtedy, gdy byłoby dobrze/źle używać zmiennej globalnej.
 12
Author: Eli Courtwright,
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-09-17 19:24:58

Modern C++ Design by Alexandrescu ma bezpieczną dla wątku, dziedziczoną generyczną singleton.

Dla mojego 2P-warto, myślę, że ważne jest, aby mieć zdefiniowane życia dla singletons (kiedy jest to absolutnie konieczne, aby z nich korzystać). Normalnie nie pozwalam funkcji static get() tworzyć instancji czegokolwiek, a konfigurację i zniszczenie pozostawiam jakiejś dedykowanej sekcji głównej aplikacji. Pomaga to uwypuklić zależności między singletonami - ale, jak podkreślono powyżej, najlepiej jest po prostu unikaj ich, jeśli to możliwe.

 6
Author: tenpn,
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
2016-01-07 09:50:03
  • Jak poprawnie zaimplementować Singleton
Jest jeden problem, o którym nigdy nie wspomniałem, coś, na co natknąłem się w poprzedniej pracy. Mieliśmy singletony C++, które były współdzielone między bibliotekami dll, a zwykła mechanika zapewnienia, że pojedyncza instancja klasy po prostu nie działa. Problem polega na tym, że każda DLL dostaje swój własny zestaw zmiennych statycznych, wraz z EXE. Jeśli twoja funkcja get_instance jest wbudowana lub częścią biblioteki statycznej, każda DLL zakończy się z jej własna Kopia "Singletona".

Rozwiązaniem jest upewnienie się, że kod singleton jest zdefiniowany tylko w jednej DLL lub EXE, lub utworzenie menedżera singleton z tymi właściwościami do rozdzielania instancji.

 6
Author: Mark Ransom,
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
2016-01-07 09:50:55

Pierwszy przykład nie jest bezpieczny dla wątków - jeśli dwa wątki wywołają getInstance w tym samym czasie, to statyczna będzie PITA. Przydałaby się jakaś forma mutexu.

 5
Author: Rob,
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-09-17 19:20:13

Jak zauważyli inni, głównymi wadami singletonów jest niemożność ich rozszerzenia i utrata możliwości tworzenia instancji więcej niż jednej instancji, np. w celach testowych.

Kilka przydatnych aspektów singletonów:

  1. lazy or upfront instantiation
  2. przydatne dla obiektu, który wymaga ustawienia i / lub stanu

Jednak nie musisz używać Singletona, aby uzyskać te korzyści. Możesz napisać normalny obiekt, który wykonuje pracę, a następnie mieć ludzi dostęp do niego przez fabrykę (osobny obiekt). Fabryka może martwić się tylko o utworzenie jednego i ponowne użycie go itp. w razie potrzeby. Ponadto, jeśli programujesz do interfejsu, a nie konkretnej klasy, fabryka może używać strategii, tzn. możesz przełączać się i wyłączać różne implementacje interfejsu.

Wreszcie, fabryka nadaje się do technologii wtrysku zależności, takich jak Spring itp.

 4
Author: 2 revs, 2 users 81%lexh,
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
2016-01-07 09:52:37

Singletony są przydatne, gdy masz dużo kodu uruchamianego podczas inicjalizacji i sprzeciwu. Na przykład, gdy używasz iBatis podczas konfigurowania obiektu persistence musi on odczytać wszystkie konfiguracje, przeanalizować mapy, upewnić się, że wszystko jest poprawne, itd.. zanim przejdziesz do kodu.

Gdybyś robił to za każdym razem, wydajność byłaby znacznie pogorszona. Używając go w singletonie, bierzesz to uderzenie raz, a potem wszystkie kolejne połączenia nie muszą tego robić.

 3
Author: Brian,
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-09-17 19:28:22

Prawdziwym upadkiem singletonów jest to, że łamią dziedzictwo. Nie możesz uzyskać nowej klasy dającej rozszerzoną funkcjonalność, chyba że masz dostęp do kodu, do którego odwołuje się Singleton. Tak więc, poza faktem Singleton będzie Twój kod ściśle powiązane (fixable przez wzór strategii ... aka Dependency Injection) uniemożliwi to również zamknięcie sekcji kodu przed rewizją (biblioteki współdzielone).

Więc nawet przykłady loggerów czy puli wątków są nieprawidłowe i powinny być zastąpione przez strategie.

 3
Author: ZebZiggle,
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-09-17 19:33:19

Większość ludzi używa singletonów, gdy starają się poczuć się dobrze używając zmiennej globalnej. Istnieją uzasadnione zastosowania, ale większość czasu, gdy ludzie z nich korzystają, fakt, że może być tylko jeden przypadek, jest po prostu banalnym faktem w porównaniu z faktem, że jest dostępny globalnie.

 3
Author: Brad Barker,
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-04-17 19:09:19

Ponieważ singleton pozwala na utworzenie tylko jednej instancji, skutecznie kontroluje replikację instancji. na przykład nie potrzebujesz wielu instancji wyszukiwania-na przykład Mapy wyszukiwania morse ' a, więc owijanie jej w klasę singleton jest apt. I tylko dlatego, że masz pojedynczą instancję klasy, nie oznacza to, że masz również ograniczoną liczbę odwołań do tej instancji. Możesz kolejkować połączenia (aby uniknąć problemów z wątkiem) do wystąpienia i wprowadzać niezbędne zmiany. Tak, generał. forma Singletona jest globalnie publiczna, z pewnością możesz zmodyfikować projekt, aby stworzyć bardziej ograniczony dostęp do Singletona. Nie męczyłem tego wcześniej, ale wiem, że to możliwe. A do wszystkich tych, którzy komentowali, że wzór Singletona jest całkowicie zły, powinieneś wiedzieć: tak, jest zły, jeśli nie używasz go właściwie lub w granicach skutecznej funkcjonalności i przewidywalnego zachowania: nie UOGÓLNIAJ.

 3
Author: gogole,
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-08-01 12:41:53

Ale kiedy potrzebuję czegoś takiego jak Singleton, często kończę używając licznika Schwarza , aby go utworzyć.

 2
Author: Matt Cruikshank,
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-09-17 19:44:56

Używam singletonów jako testu na rozmowę kwalifikacyjną.

Kiedy Proszę dewelopera o nazwanie niektórych wzorców projektowych, jeśli wszystko, co może wymienić, to Singleton, nie jest zatrudniony.

 1
Author: Matt Cruikshank,
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-09-17 19:40:26

Poniżej znajduje się lepsze podejście do implementacji bezpiecznego wzorca Singletona z dealokacją pamięci w samym destruktorze. Ale myślę, że Destruktor powinien być opcjonalny, ponieważ instancja Singletona zostanie automatycznie zniszczona po zakończeniu programu:

#include<iostream>
#include<mutex>

using namespace std;
std::mutex mtx;

class MySingleton{
private:
    static MySingleton * singletonInstance;
    MySingleton();
    ~MySingleton();
public:
    static MySingleton* GetInstance();
    MySingleton(const MySingleton&) = delete;
    const MySingleton& operator=(const MySingleton&) = delete;
    MySingleton(MySingleton&& other) noexcept = delete;
    MySingleton& operator=(MySingleton&& other) noexcept = delete;
};

MySingleton* MySingleton::singletonInstance = nullptr;
MySingleton::MySingleton(){ };
MySingleton::~MySingleton(){
    delete singletonInstance;
};

MySingleton* MySingleton::GetInstance(){
    if (singletonInstance == NULL){
        std::lock_guard<std::mutex> lock(mtx);
        if (singletonInstance == NULL)
            singletonInstance = new MySingleton();
    }
    return singletonInstance;
}

Odnośnie sytuacji, w których musimy użyć klas singleton, można- Jeśli chcemy zachować stan instancji przez cały czas wykonywania programu Jeśli jesteśmy zaangażowani w pisanie do egzekucji dziennik aplikacji, w której należy użyć tylko jednej instancji pliku....i tak dalej. Będzie to odczuwalne, jeśli ktoś może zasugerować optymalizację w moim powyższym kodzie.

 1
Author: A. Gupta,
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-08-11 20:25:45

Przeciw Użyciu:

Jednym z głównych problemów z nadmiernym używaniem Singletona jest to, że wzorzec zapobiega łatwemu rozszerzaniu i zamianie alternatywnych implementacji. Nazwa klasy jest zakodowana wszędzie tam, gdzie używany jest singleton.

 0
Author: Adam Franco,
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-09-17 19:26:16

Myślę, że to jest najbardziej solidna wersja dla C#:

using System;
using System.Collections;
using System.Threading;

namespace DoFactory.GangOfFour.Singleton.RealWorld
{

  // MainApp test application

  class MainApp
  {
    static void Main()
    {
      LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b4 = LoadBalancer.GetLoadBalancer();

      // Same instance?
      if (b1 == b2 && b2 == b3 && b3 == b4)
      {
        Console.WriteLine("Same instance\n");
      }

      // All are the same instance -- use b1 arbitrarily
      // Load balance 15 server requests
      for (int i = 0; i < 15; i++)
      {
        Console.WriteLine(b1.Server);
      }

      // Wait for user
      Console.Read();    
    }
  }

  // "Singleton"

  class LoadBalancer
  {
    private static LoadBalancer instance;
    private ArrayList servers = new ArrayList();

    private Random random = new Random();

    // Lock synchronization object
    private static object syncLock = new object();

    // Constructor (protected)
    protected LoadBalancer()
    {
      // List of available servers
      servers.Add("ServerI");
      servers.Add("ServerII");
      servers.Add("ServerIII");
      servers.Add("ServerIV");
      servers.Add("ServerV");
    }

    public static LoadBalancer GetLoadBalancer()
    {
      // Support multithreaded applications through
      // 'Double checked locking' pattern which (once
      // the instance exists) avoids locking each
      // time the method is invoked
      if (instance == null)
      {
        lock (syncLock)
        {
          if (instance == null)
          {
            instance = new LoadBalancer();
          }
        }
      }

      return instance;
    }

    // Simple, but effective random load balancer

    public string Server
    {
      get
      {
        int r = random.Next(servers.Count);
        return servers[r].ToString();
      }
    }
  }
}

Oto . NET-wersja zoptymalizowana :

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Singleton.NETOptimized
{

  // MainApp test application

  class MainApp
  {

    static void Main()
    {
      LoadBalancer b1 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b2 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b3 = LoadBalancer.GetLoadBalancer();
      LoadBalancer b4 = LoadBalancer.GetLoadBalancer();

      // Confirm these are the same instance
      if (b1 == b2 && b2 == b3 && b3 == b4)
      {
        Console.WriteLine("Same instance\n");
      }

      // All are the same instance -- use b1 arbitrarily
      // Load balance 15 requests for a server
      for (int i = 0; i < 15; i++)
      {
        Console.WriteLine(b1.Server);
      }

      // Wait for user
      Console.Read();    
    }
  }

  // Singleton

  sealed class LoadBalancer
  {
    // Static members are lazily initialized.
    // .NET guarantees thread safety for static initialization
    private static readonly LoadBalancer instance =
      new LoadBalancer();

    private ArrayList servers = new ArrayList();
    private Random random = new Random();

    // Note: constructor is private.
    private LoadBalancer()
    {
      // List of available servers
      servers.Add("ServerI");
      servers.Add("ServerII");
      servers.Add("ServerIII");
      servers.Add("ServerIV");
      servers.Add("ServerV");
    }

    public static LoadBalancer GetLoadBalancer()
    {
      return instance;
    }

    // Simple, but effective load balancer
    public string Server
    {
      get
      {
        int r = random.Next(servers.Count);
        return servers[r].ToString();
      }
    }
  }
}

Możesz znaleźć ten wzór na dotfactory.com .

 0
Author: artur02,
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-09-17 19:27:22

Wzór Meyersa Singletona działa wystarczająco dobrze przez większość czasu, a przy okazji robi to niekoniecznie opłaca się szukać czegoś lepszego. Tak długo, jak konstruktor nigdy nie rzuci i nie ma zależności między singletonami.

Singleton jest implementacją dla globalnie dostępnego obiektu (od teraz GAO), chociaż nie wszystkie Gao są singletonami.

Loggery same nie powinny być singletonami, ale środki do logowania powinny być globalnie dostępny, aby oddzielić miejsce generowania wiadomości dziennika od miejsca i sposobu jej rejestrowania.

Lazy-loading / Lazy evaluation jest inną koncepcją i singleton Zwykle ją implementuje. Ma wiele własnych problemów, w szczególności wątek-Bezpieczeństwo i problemy, jeśli zawiedzie z wyjątkami takimi, że to, co wydawało się dobrym pomysłem w tym czasie, okazuje się jednak nie być takie świetne. (Trochę jak implementacja krowy w strunach).

Mając to na uwadze, GOAs może być inicjowane tak:

namespace {

T1 * pt1 = NULL;
T2 * pt2 = NULL;
T3 * pt3 = NULL;
T4 * pt4 = NULL;

}

int main( int argc, char* argv[])
{
   T1 t1(args1);
   T2 t2(args2);
   T3 t3(args3);
   T4 t4(args4);

   pt1 = &t1;
   pt2 = &t2;
   pt3 = &t3;
   pt4 = &t4;

   dostuff();

}

T1& getT1()
{
   return *pt1;
}

T2& getT2()
{
   return *pt2;
}

T3& getT3()
{
  return *pt3;
}

T4& getT4()
{
  return *pt4;
}

Nie trzeba tego robić tak brutalnie, i wyraźnie w załadowanej bibliotece, która zawiera obiekty, prawdopodobnie potrzebujesz innego mechanizmu do zarządzania ich żywotnością. (Umieść je w obiekcie, który otrzymujesz podczas ładowania biblioteki).

A kiedy używam singletonów? Użyłem ich do 2 rzeczy - Tabela singletonowa, która wskazuje, jakie biblioteki zostały załadowane za pomocą dlopen - Obsługa wiadomości, do której rejestratorzy mogą się zapisać i do której można wysyłać wiadomości za. Wymagane specjalnie do obsługi sygnałów.

 0
Author: CashCow,
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
2011-03-02 13:09:27

Nadal nie rozumiem, dlaczego singleton musi być globalny.

Zamierzałem wyprodukować singleton, w którym ukryłem bazę danych wewnątrz klasy jako prywatną stałą statyczną zmienną i stworzyłem funkcje klasy, które wykorzystują bazę danych bez ujawniania bazy danych użytkownikowi.

Nie widzę powodu, dla którego ta funkcjonalność byłaby zła.

 0
Author: Zachary Kraus,
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
2014-01-31 03:35:23

Uważam, że są przydatne, gdy mam klasę, która hermetyzuje dużo pamięci. Na przykład w ostatniej grze, nad którą pracowałem mam klasę mapy wpływu, która zawiera zbiór bardzo dużych tablic przylegającej pamięci. Chcę, aby wszystkie przydzielone przy starcie, wszystkie zwolnione przy wyłączaniu i na pewno chcę tylko jedną kopię. Mam również dostęp do niego z wielu miejsc. Uważam, że wzór Singletona jest bardzo przydatny w tym przypadku.

Jestem pewien, że są inne rozwiązania, ale znajduję ten bardzo przydatny i łatwy do wdrożenia.

 0
Author: Michael Avraamides,
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-10-18 20:45:59

Jeśli jesteś twórcą Singletona i używasz go, nie rób z niego Singletona (nie ma to sensu, ponieważ możesz kontrolować osobliwość obiektu bez tworzenia Singletona), ale ma to sens, gdy jesteś programistą biblioteki i chcesz dostarczyć tylko jeden obiekt użytkownikom (w tym przypadku jesteś tym, który stworzył singleton, ale nie jesteś użytkownikiem).

Singletony są obiektami, więc używaj ich jako obiektów, Wiele osób uzyskuje dostęp do singletonów bezpośrednio przez wywołanie metody, która go zwraca, ale jest to szkodliwe, ponieważ robisz kod wie, że obiekt jest singletonem, ja wolę używać singletonów jako obiektów, przekazuję je przez konstruktor i używam ich jako zwykłych obiektów, w ten sposób, Twój kod nie wie, czy te obiekty są singletonami, czy nie, a to sprawia, że zależności są bardziej jasne i pomaga trochę w refaktoryzacji ...

 0
Author: La VloZ Merrill,
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-07-28 17:14:28

W aplikacjach desktopowych (wiem, Tylko my dinozaury je piszą!) są one niezbędne do uzyskania względnie niezmiennych globalnych ustawień aplikacji - języka użytkownika, ścieżki do plików pomocy, preferencji użytkownika itp., które w przeciwnym razie musiałyby być wprowadzane do każdej klasy i każdego okna dialogowego.

Edit-oczywiście powinny być tylko do odczytu !

 -1
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-09-28 03:36:13

Kolejna implementacja

class Singleton
{
public:
    static Singleton& Instance()
    {
        // lazy initialize
        if (instance_ == NULL) instance_ = new Singleton();

        return *instance_;
    }

private:
    Singleton() {};

    static Singleton *instance_;
};
 -1
Author: user1135926,
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
2012-01-07 17:10:33