O wzorach projektowych: Kiedy powinienem używać singletonu?


448

Gloryfikowana zmienna globalna - staje się chwalebną klasą globalną. Niektórzy twierdzą, że łamanie zorientowanego obiektowo projektu.

Podaj mi scenariusze inne niż stary dobry rejestrator, w którym sensowne jest użycie singletonu.


4
Od czasu nauki erlang wolę takie podejście, a mianowicie niezmienność i przekazywanie wiadomości.
Setori

209
Co nie jest konstruktywne w tym pytaniu? Widzę konstruktywną odpowiedź poniżej.
mk12

3
Struktura wstrzykiwania zależności jest bardzo złożonym singletonem, który daje obiekt….
Ian Ringrose

1
Singleton może być używany jako obiekt menedżera między instancjami innych obiektów, dlatego powinna istnieć tylko jedna instancja singletonu, w której każda inna instancja powinna komunikować się za pośrednictwem instancji singleton.
Levent Divilioglu

Mam pytanie poboczne: każdą implementację Singletona można również zaimplementować przy użyciu klasy „statycznej” (przy użyciu metody „factory” / „init”) - bez tworzenia instancji klasy (można powiedzieć, że klasa statyczna jest rodzaj implementacji Singleton, ale ...) - dlaczego należy używać rzeczywistego Singleton (instancja pojedynczej klasy, która upewnia się, że jest singlem) zamiast klasy statycznej? Jedynym powodem, dla którego mogę wymyślić, jest „semantyka”, ale nawet w tym sensie przypadki użycia Singleton tak naprawdę nie wymagają z definicji relacji „klasa-> instancja” ... więc ... dlaczego?
Yuval A.

Odpowiedzi:


358

W mojej pogoni za prawdą odkryłem, że tak naprawdę jest bardzo niewiele „akceptowalnych” powodów, aby używać Singletona.

Jednym z powodów, który często pojawia się w sieci, jest klasa „rejestrowania” (o której wspominałeś). W takim przypadku Singleton może być użyty zamiast pojedynczej instancji klasy, ponieważ klasa rejestrowania zwykle musi być używana w kółko przez każdą klasę w projekcie. Jeśli każda klasa korzysta z tej klasy rejestrowania, wstrzykiwanie zależności staje się niewygodne.

Rejestrowanie jest szczególnym przykładem „akceptowalnego” Singletona, ponieważ nie wpływa on na wykonanie twojego kodu. Wyłącz rejestrowanie, wykonywanie kodu pozostaje takie samo. Włącz to samo. Misko umieszcza to w następujący sposób w Root Cause of Singletons : „Informacje przepływają tutaj w jedną stronę: z aplikacji do rejestratora. Mimo że rejestratory są stanem globalnym, ponieważ żadne informacje nie przepływają z rejestratorów do aplikacji, rejestratory są dopuszczalne”.

Jestem pewien, że istnieją również inne ważne powody. Alex Miller w „ Wzorcach, których nienawidzę ”, mówi o lokalizatorach usług i interfejsie użytkownika po stronie klienta, które są prawdopodobnie „akceptowalnymi” wyborami.

Czytaj więcej na Singleton Kocham cię, ale mnie poniżasz.


3
@ArneMertz Myślę, że to jest ten.
Attacktive

1
Dlaczego nie możesz po prostu użyć obiektu globalnego? Dlaczego to musi być singleton?
But

1
Myślę, że statyczna metoda na użytkowanie logowania?
Skynet

1
Singletony są najlepsze, gdy trzeba zarządzać zasobami. Na przykład połączenia HTTP. Nie chcesz ustanawiać 1 miliona klientów HTTP dla jednego klienta, co jest szalone marnotrawstwem i powolne. Tak więc singleton z połączonym klientem HTTP będzie znacznie szybszy i przyjazny dla zasobów.
Cogman,

3
Wiem, że to stare pytanie, a informacje zawarte w tej odpowiedzi są świetne. Mam jednak problem ze zrozumieniem, dlaczego jest to akceptowana odpowiedź, kiedy PO jasno sprecyzowało: „Podaj mi scenariusze inne niż stary dobry rejestrator, w którym sensowne jest użycie singletonu”.
Francisco C.

124

Kandydat Singleton musi spełniać trzy wymagania:

  • kontroluje równoczesny dostęp do udostępnionego zasobu.
  • dostęp do zasobu będzie wymagany z wielu różnych części systemu.
  • może być tylko jeden obiekt.

Jeśli proponowany Singleton ma tylko jeden lub dwa z tych wymagań, przeprojektowanie jest prawie zawsze właściwą opcją.

Na przykład jest mało prawdopodobne, aby bufor drukarki był wywoływany z więcej niż jednego miejsca (menu Drukuj), więc można użyć muteksów do rozwiązania problemu z równoczesnym dostępem.

Prosty program rejestrujący jest najbardziej oczywistym przykładem potencjalnie poprawnego Singletona, ale może się to zmienić w przypadku bardziej złożonych schematów rejestrowania.


3
Nie zgadzam się z punktem 2. Punkt 3 nie jest tak naprawdę powodem (tylko dlatego, że możesz, nie oznacza, że ​​powinieneś), a 1 jest dobrym punktem, ale nadal nie widzę w tym sensu. Powiedzmy, że współużytkowanym zasobem jest napęd dyskowy lub pamięć podręczna db. Możesz dodać inny dysk lub mieć pamięć podręczną db skupiającą się na innej rzeczy (takiej jak pamięć podręczna dla specjalnej tabeli dla jednego wątku, a drugi ma bardziej ogólny cel).

15
Myślę, że przegapiłeś słowo „kandydat”. Kandydat Singleton musi spełniać trzy wymagania; tylko dlatego, że coś spełnia wymagania, nie oznacza, że ​​powinien to być singleton. Mogą występować inne czynniki projektowe :)
metao

45

Odczytywanie plików konfiguracyjnych, które powinny być odczytywane tylko podczas uruchamiania i zamykanie ich w singletonie.


8
Podobnie jak Properties.Settings.Defaultw .NET.
Nick Bedford

9
@Paul, „Obóz no-singleton” będzie stanowił, że obiekt konfiguracyjny należy po prostu przekazać do funkcji, które go potrzebują, zamiast uczynić go globalnie dostępnym (inaczej singleton).
Pacerier

2
Nie zgadzać się. Jeśli konfiguracja zostanie przeniesiona do bazy danych, wszystko jest zepsute. Jeśli ścieżka do konfiguracji zależy od czegokolwiek poza tym singletonem, te rzeczy również muszą być statyczne.
rr-

3
@PaulCroarkin Czy możesz rozwinąć tę kwestię i wyjaśnić, jak to jest korzystne?
AlexG

1
@ rr - jeśli konfiguracja zostanie przeniesiona do bazy danych, nadal można ją zamknąć w obiekcie konfiguracyjnym, który zostanie przekazany do potrzebujących jej funkcji. (PS Nie jestem w obozie „no-singleton”).
Czy Sheppard

36

Z singletonu korzystasz, gdy chcesz zarządzać udostępnionym zasobem. Na przykład bufor drukarki. Twoja aplikacja powinna mieć tylko jedną instancję bufora, aby uniknąć sprzecznego żądania dla tego samego zasobu.

Lub połączenie z bazą danych lub menedżer plików itp.


30
Słyszałem ten przykład buforu drukarki i myślę, że to trochę kiepskie. Kto powiedział, że nie mogę mieć więcej niż jednego bufora? Czym do cholery jest bufor drukarki? Co się stanie, jeśli mam różne drukarki, które nie mogą powodować konfliktów ani używać różnych sterowników?
1800 INFORMACJI

6
To tylko przykład ... w każdej sytuacji, której każdy użyje jako przykładu, będziesz w stanie znaleźć alternatywny projekt, który uczyni ten przykład bezużytecznym. Udawajmy, że bufor buforuje jeden zasób współdzielony przez wiele komponentów. To działa.
Vincent Ramdhanie

2
To klasyczny przykład Gangu Czterech. Myślę, że odpowiedź z prawdziwym wypróbowanym przypadkiem użycia byłaby bardziej przydatna. Mam na myśli sytuację, w której naprawdę uważałeś Singleton za najlepsze rozwiązanie.
Andrei Vajna II

Wspólny zasób jest moim zdaniem zbyt szerokim przykładem. W jaki sposób przetestowałbyś, że obiekty korzystające z bufora wydruku działają poprawnie w obliczu nieprawidłowego działania bufora, gdy nie możesz wstrzyknąć nieprawidłowej implementacji „bufora”? choć krótka i mało pouczająca, przyjęta odpowiedź jest o wiele bezpieczniejszym podejściem w mojej książce
Rune FS

Czym do cholery jest bufor drukarki?
RayLoveless

23

Tylko do odczytu singletony przechowujące stan globalny (język użytkownika, ścieżka pliku pomocy, ścieżka aplikacji) są rozsądne. Uważaj na używanie singletonów do kontrolowania logiki biznesowej - pojedynczy prawie zawsze kończy się wieloma


4
Językiem użytkownika może być singleton, przy założeniu, że tylko jeden użytkownik może korzystać z systemu.
Samuel Åslund,

… A ten użytkownik mówi tylko jednym językiem.
spectras

17

Zarządzanie połączeniem (lub pulą połączeń) z bazą danych.

Użyłbym tego również do pobierania i przechowywania informacji w zewnętrznych plikach konfiguracyjnych.


2
Czy generator połączeń z bazą danych nie byłby przykładem fabryki?
Ken

3
@ Ken chciałbyś, aby ta fabryka była singletonem w prawie wszystkich przypadkach.
Chris Marisic

2
@Federico, „Obóz no-singleton” oznajmi, że te połączenia z bazą danych należy po prostu przekazać do funkcji, które ich potrzebują, zamiast uczynić je globalnie dostępnymi (inaczej singleton).
Pacerier

3
Naprawdę nie potrzebujesz do tego singletona. Można go wstrzyknąć.
Nestor Ledon

11

Jednym ze sposobów korzystania z singletonu jest pokrycie instancji, w której musi istnieć pojedynczy „broker” kontrolujący dostęp do zasobu. Singletony są dobre w programach rejestrujących, ponieważ pośredniczą w dostępie do, powiedzmy, pliku, do którego można zapisać wyłącznie. W przypadku czegoś takiego jak rejestrowanie, zapewniają one sposób wyodrębnienia zapisów do czegoś takiego jak plik dziennika - możesz zawinąć mechanizm buforowania w singletonie itp.

Pomyśl także o sytuacji, w której masz aplikację z wieloma oknami / wątkami / itp., Ale która wymaga jednego punktu komunikacji. Kiedyś użyłem jednego do kontrolowania zadań, które chciałem uruchomić moją aplikację. Singleton był odpowiedzialny za serializację zadań i wyświetlanie ich statusu w dowolnej innej części programu, która była zainteresowana. W tego rodzaju scenariuszu możesz spojrzeć na singleton jako coś w rodzaju klasy „serwerowej” działającej w Twojej aplikacji ... HTH


3
Rejestratory są najczęściej singletonami, więc obiekty rejestrujące nie muszą być przekazywane. Każda przyzwoita implementacja strumienia dziennika zapewni, że jednoczesne zapisy będą niemożliwe, niezależnie od tego, czy jest to Singleton, czy nie.
metao

10

Do zarządzania dostępem do zasobu współużytkowanego przez całą aplikację powinien być używany singleton, a potencjalnie posiadanie wielu wystąpień tej samej klasy byłoby destrukcyjne. Zapewnienie, że dostęp do wątku współdzielonego jest bezpieczny, jest bardzo dobrym przykładem tego, gdzie tego rodzaju wzorzec może być niezbędny.

Korzystając z Singletonów, upewnij się, że przypadkowo nie ukrywasz zależności. Idealnie, singletony (jak większość zmiennych statycznych w aplikacji) są konfigurowane podczas wykonywania kodu inicjalizacji aplikacji (static void Main () dla plików wykonywalnych C #, static void main () dla plików wykonywalnych Java), a następnie przekazywane do wszystkie inne klasy, które są tworzone, które tego wymagają. Pomaga to utrzymać testowalność.


8

Myślę, że użycie singletonu można traktować tak samo jak relację wiele do jednego w bazach danych. Jeśli masz wiele różnych części kodu, które muszą współpracować z pojedynczą instancją obiektu, to właśnie wtedy sensowne jest użycie singletonów.


6

Praktyczny przykład singletona można znaleźć w Test :: Builder , klasie, która wspiera prawie każdy nowoczesny moduł testujący Perla. Singleton Test :: Builder przechowuje i brokuje stan i historię procesu testowego (historyczne wyniki testu, zlicza liczbę uruchomionych testów), a także rzeczy takie jak miejsce, w którym idzie wynik testu. Wszystkie są niezbędne do koordynowania wielu modułów testowych napisanych przez różnych autorów, aby współpracować w jednym skrypcie testowym.

Historia singla Test :: Builder ma charakter edukacyjny. Wywołanie new()zawsze daje ten sam obiekt. Po pierwsze, wszystkie dane były przechowywane jako zmienne klas bez niczego w samym obiekcie. Działało to do momentu, gdy sam chciałem przetestować Test :: Builder. Następnie potrzebowałem dwóch obiektów Test :: Builder, jednego zestawu jako manekina, aby uchwycić i przetestować jego zachowanie i dane wyjściowe, a drugiego być prawdziwym obiektem testowym. W tym momencie Test :: Builder został przekształcony w prawdziwy obiekt. Obiekt singletonu był przechowywany jako dane klasy i new()zawsze go zwracał. create()został dodany, aby utworzyć świeży obiekt i umożliwić testowanie.

Obecnie użytkownicy chcą zmienić niektóre zachowania Test :: Builder we własnym module, ale zostawić inne w spokoju, podczas gdy historia testów pozostaje wspólna dla wszystkich modułów testujących. To, co się teraz dzieje, to monolityczny obiekt Test :: Builder jest rozkładany na mniejsze części (historia, dane wyjściowe, format ...), a instancja Test :: Builder zbiera je razem. Teraz Test :: Builder nie musi już być singletonem. Składniki, takie jak historia, mogą być. Spycha to nieelastyczną potrzebę singletona na niższy poziom. Daje użytkownikowi większą elastyczność w mieszaniu i dopasowywaniu elementów. Mniejsze obiekty singletonowe mogą teraz po prostu przechowywać dane, a zawierające je obiekty decydują o tym, jak z nich korzystać. Pozwala nawet na grę poza klasą :: Test :: Builder za pomocą historii Test :: Builder i singletonów wyjściowych.

Wydaje się, że istnieje koordynacja danych z elastycznością zachowań, którą można złagodzić, umieszczając singleton wokół tylko współdzielonych danych z możliwie najmniejszym zachowaniem, aby zapewnić integralność danych.


5

Gdy ładujesz obiekt właściwości konfiguracji, albo z bazy danych, albo z pliku, pomaga zachować go jako singleton; nie ma powodu, aby nadal odczytywać dane statyczne, które nie zmienią się podczas działania serwera.


2
Dlaczego nie wystarczy raz załadować dane i przekazać obiekt konfiguracyjny w razie potrzeby?
lagweezle

co jest z przekazywaniem ??? Gdybym musiał omijać każdy potrzebny mi obiekt, miałbym konstruktorów z 20 argumentami ...
Enerccio,

@Enerccio Jeśli masz obiekty, które opierają się na 20 różnych innych obiektach bez hermetyzacji, masz już poważne problemy projektowe.
spectras

@spectras Do I? Jeśli zaimplementuję okno dialogowe GUI, będę potrzebować: repozytorium, lokalizacji, danych sesji, danych aplikacji, elementu nadrzędnego widgetu, danych klienta, menedżera uprawnień i prawdopodobnie więcej. Jasne, możesz agregować niektóre, ale dlaczego? Osobiście używam wiosny i aspektów, aby po prostu automatycznie przypisać wszystkie te zależności do klasy widżetu, a to wszystko oddziela.
Enerccio

Jeśli masz taki stan, możesz rozważyć wdrożenie fasady, podając odpowiednie aspekty konkretnego kontekstu. Dlaczego? Ponieważ pozwoliłoby to na czystą konstrukcję bez antipatternów konstruktora singleton lub 29-arg. W rzeczywistości sam fakt, że twoje okno dialogowe GUI ma dostęp do wszystkich tych rzeczy, krzyczy „naruszenie zasady pojedynczej odpowiedzialności”.
spectras

3

Jak wszyscy mówili, wspólny zasób - konkretnie coś, co nie może obsłużyć równoczesnego dostępu.

Jednym konkretnym przykładem, który widziałem, jest Lucene Search Index Writer.


1
A jednak IndexWriter nie jest singlem ...
Mark,

3

Możesz użyć Singleton podczas implementacji wzorca stanu (w sposób pokazany w książce GoF). Jest tak, ponieważ konkretne klasy stanu nie mają własnego stanu i wykonują swoje działania w kategoriach klasy kontekstu.

Możesz także sprawić, że Abstract Factory stanie się singletonem.


Właśnie z tym mam teraz do czynienia w projekcie. Użyłem wzorca stanu do usunięcia powtarzającego się kodu warunkowego z metod kontekstu. Stan nie ma własnych zmiennych instancji. Jestem jednak na płocie w kwestii tego, czy powinienem je uczynić singletonami. Za każdym razem, gdy stan zmienia się, tworzona jest instancja nowej instancji. Wydaje się to marnotrawstwem, ponieważ w żaden sposób instancja nie może różnić się od innej (ponieważ nie ma zmiennych instancji). Próbuję dowiedzieć się, dlaczego nie powinienem tego używać.
kiwicomb123

1
@ kiwicomb123 Postaraj się, abyś był setState()odpowiedzialny za decydowanie o polityce tworzenia stanu. Pomaga, jeśli Twój język programowania obsługuje szablony lub ogólne. Zamiast Singleton można użyć wzorca Monostate , w którym tworzenie instancji obiektu stanu powoduje ponowne użycie tego samego globalnego / statycznego obiektu stanu. Składnia zmiany stanu może pozostać niezmieniona, ponieważ użytkownicy nie muszą być świadomi, że utworzony stan jest monostatem.
Emile Cormier

Okej, więc w moich stanach mógłbym po prostu ustawić wszystkie metody na statyczne, więc za każdym razem, gdy tworzona jest nowa instancja, nie ma tego samego obciążenia? Jestem trochę zdezorientowany, muszę przeczytać o wzorze Monostate.
kiwicomb123

@ kiwicomb123 Nie, w Monostate nie chodzi o to, aby wszyscy członkowie byli statyczni. Lepiej przeczytaj na ten temat, a następnie sprawdź SO pod kątem powiązanych pytań i odpowiedzi.
Emile Cormier

Uważam, że powinno to mieć więcej głosów. Fabryka abstrakcyjna jest dość powszechna, a ponieważ fabryki są bezstanowe, stabilne pod względem bycia bezstanowymi i nie można ich wdrożyć metodami statycznymi (w Javie), które nie są nadpisywane, użycie singletonu powinno być w porządku.
DPM

3

Wspólne zasoby. Zwłaszcza w PHP, klasie bazy danych, klasie szablonów i klasie globalnych magazynów zmiennych. Wszystkie muszą być współużytkowane przez wszystkie moduły / klasy używane w całym kodzie.

Jest to prawdziwe użycie obiektu -> klasa szablonów zawiera budowany szablon strony, który jest kształtowany, dodawany, zmieniany przez moduły dodające do danych wyjściowych strony. Musi być przechowywany jako pojedyncza instancja, aby tak się stało, to samo dotyczy baz danych. Dzięki współużytkowanemu singletonowi bazy danych wszystkie klasy modułów mogą uzyskać dostęp do zapytań i uzyskać je bez konieczności ich ponownego uruchamiania.

Singleton globalnego składu zmiennych zapewnia globalny, niezawodny i łatwy w użyciu skład zmiennych. Bardzo porządkuje Twój kod. Wyobraź sobie, że wszystkie wartości konfiguracji znajdują się w tablicy w singletonie, np .:

$gb->config['hostname']

lub posiadanie wszystkich wartości językowych w tablicy takiej jak:

$gb->lang['ENTER_USER']

Pod koniec uruchamiania kodu strony otrzymujesz, powiedzmy, teraz dojrzały:

$template

Singleton, $gbsingleton, który ma tablicę językową do zastąpienia go i wszystkie dane wyjściowe są załadowane i gotowe. Po prostu zamienisz je na klucze obecne w wartości strony obiektu dojrzałego szablonu, a następnie podasz je użytkownikowi.

Ogromną zaletą tego jest to, że możesz wykonać DOWOLNĄ obróbkę końcową na dowolnym urządzeniu. Możesz przesyłać wszystkie wartości językowe do tłumaczeń google lub innej usługi tłumaczeniowej i odzyskać je, a następnie zamienić na odpowiednie miejsca, na przykład przetłumaczone. lub możesz zastępować w strukturach strony lub ciągach treści, jak chcesz.


21
Możesz podzielić swoją odpowiedź na wiele akapitów i zablokować segmenty kodu dla zapewnienia czytelności.
Justin

1

Konfigurowanie określonych problemów związanych z infrastrukturą jako singletonów lub zmiennych globalnych może być bardzo pragmatyczne. Moim ulubionym przykładem są frameworki Dependency Injection, które wykorzystują singletony do działania jako punkt połączenia z frameworkiem.

W takim przypadku polegasz na infrastrukturze, aby uprościć korzystanie z biblioteki i uniknąć niepotrzebnej złożoności.


0

Używam go do obiektów enkapsulujących parametry wiersza poleceń podczas pracy z modułami wtykowymi. Główny program nie wie, jakie są parametry wiersza poleceń dla modułów, które się ładują (i nie zawsze nawet wie, które moduły są ładowane). np. główne obciążenia A, które same nie potrzebują żadnych parametrów (więc dlaczego powinien wziąć dodatkowy wskaźnik / odniesienie / cokolwiek, nie jestem pewien - wygląda jak zanieczyszczenie), a następnie ładuje moduły X, Y i Z. Dwa z nich, powiedzmy X i Z, potrzebujesz (lub akceptuje) parametry, więc wywołują z powrotem do singletonu wiersza poleceń, aby powiedzieć mu, jakie parametry zaakceptować, a w czasie wykonywania wywołują z powrotem, aby dowiedzieć się, czy użytkownik faktycznie podał jakieś z nich.

Pod wieloma względami singleton do obsługi parametrów CGI działałby podobnie, jeśli używasz tylko jednego procesu na zapytanie (inne metody mod_ * tego nie robią, więc byłoby źle - stąd argument, że nie powinieneś „ t używaj singletonów w świecie mod_cgi na wypadek, gdybyś portował do mod_perl lub dowolnego innego świata).


-1

Być może przykład z kodem.

Tutaj ConcreteRegistry jest singlem w pokerze, który pozwala zachowaniom w górę drzewa pakietów uzyskać dostęp do kilku podstawowych interfejsów gry (tj. Fasad modelu, widoku, kontrolera, środowiska itp.):

http://www.edmundkirwan.com/servlet/fractal/cs1/frac-cs40.html

Ed.


1
Link jest teraz zepsuty, ale jeśli rejestrujesz informacje o widoku w singletonie, do których będzie można uzyskać dostęp w całej aplikacji, nie masz sensu MVC. Widok jest aktualizowany przez (i komunikuje się) kontroler, który korzysta z modelu. Jak to tutaj brzmi, prawdopodobnie jest to niewłaściwe użycie Singletona i refaktoryzacja jest w porządku.
drharris

-9

1 - Komentarz do pierwszej odpowiedzi:

Nie zgadzam się ze statyczną klasą Logger. może to być praktyczne w przypadku implementacji, ale nie może być zastąpione w testach jednostkowych. Klasy statycznej nie można zastąpić podwójnym testem. Jeśli nie przeprowadzisz testu jednostkowego, nie zobaczysz tutaj problemu.

2 - Staram się nie tworzyć singletonu ręcznie. Po prostu tworzę prosty obiekt z konstruktorami, który pozwala mi wstrzykiwać współpracowników do obiektu. Gdybym potrzebował singletona, użyłbym frameworku wyboru zależności (Spring.NET, Unity dla .NET, Spring dla Java) lub innego.


11
Powinieneś komentować odpowiedzi bezpośrednio, klikając link na dole odpowiedzi; w ten sposób jest o wiele łatwiej. Odpowiedź, którą zobaczyłeś na górze, prawdopodobnie nie jest pierwsza. Odpowiedzi cały czas zmieniają kolejność.
Ross

dlaczego chcesz rejestrować testy jednostkowe?
Enerccio,

Istnieje ogromna różnica między „statyczną klasą Logger” a statyczną instancją Logger . Wzorzec singletonu nie mówi „uczyń klasę statyczną”, ale mówi, aby uzyskać dostęp do instancji obiektu statycznego. Na przykład, gdy ILogger logger = Logger.SingleInstance();ta metoda jest statyczna i zwraca statycznie zachowaną instancję ILoggera. Użyłeś przykładu „środowiska wstrzykiwania zależności”. Prawie wszystkie pojemniki DI są singletonami; ich konfiguracje są zdefiniowane statycznie i ostatecznie dostępne z / przechowywane w interfejsie jednego usługodawcy.
Jon Davis,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.