Wstrzykiwanie zależności i Singleton. Czy są to dwie zupełnie różne koncepcje?

17

Słyszałem o zastosowaniu zastrzyku zależności od Singletona dla mojego kolegi. Nadal nie mogę zrozumieć, czy są to dwa ortogonalne wzory, które można ze sobą zastąpić? A może DI jest metodą na przetestowanie wzorca Singleton?

Proszę spojrzeć na następujący fragment kodu.

    IMathFace obj = Singleton.Instance;

    SingletonConsumer singConsumer = new SingletonConsumer(obj);

    singConsumer.ConsumerAdd(10,20);

SingletonConsumerPrzyjmuje parametr typu IMathFace. Zamiast wewnętrznego dostępu do klasy singleton, SingletonConsumerwywoływana jest instancja singleton przekazywana przez program wywołujący. Czy to dobry przykład spożywania klasy singleton poprzez wstrzykiwanie zależności?

dzienniki
źródło
Czy możesz mi powiedzieć, w jaki sposób DI może zastąpić singleton?
7
Singleton to wzorzec projektowy. DI / IoC jest techniką.
Dave
2
DI nie może zastąpić Singletona tak, jak banan nie zastąpiłby gaźnika. To zupełnie inne pojęcia.
Dave
więc mój przykład jest poprawny.
1
Tak, ale może to nastąpić kosztem enkapsulacji (co jest również prawdą w przypadku singletonów) patrz: stackoverflow.com/questions/1005473/...

Odpowiedzi:

17

Myślę, że miał na myśli, że powinieneś użyć wstrzykiwania zależności, aby wstrzyknąć jedną instancję usługi, zamiast klasycznej implementacji Singleton ze statycznym akcesorium MySingleton.Instance.

public class MySingleton
{
    public static MySingleton Instance{get{...}};
}

Dzięki klasycznej implementacji singletonu cały kod zależy od tego, czy ta usługa jest singletonem. Zasadniczo zaimplementujesz to założenie, aby używać kodu przy każdym użyciu MySingleton.Instance.

Z drugiej strony dzięki DI otrzymujesz instancję usługi przekazaną do twojego konstruktora i przechowujesz ją. To, że istnieje tylko jedna instancja tej usługi, jest szczegółem implementacji. Możesz go łatwo zmienić, aby nadać konsumpcyjnemu kodowi inną instancję. W ten sposób masz pewną klasę / interfejs, który jest zaimplementowany przez jedną instancję, zamiast wymuszać, że jest tylko jedna instancja.

Jest to przydatne, jeśli na przykład chcesz pozorną implementację usługi do testowania lub jeśli różne części programu wymagają różnych konfiguracji tej usługi.

CodesInChaos
źródło
4

Tak masz rację. Zamiast uzyskiwać dostęp do obiektu przez singleton, przekazujesz do niego referencję, więc używasz zastrzyku konstruktora.

Inni podkreślają, że te pojęcia nie są ze sobą powiązane. Zużycie instancji singletonu nie jest niczym specjalnym, ponieważ obiekt, do którego wstrzykujesz, tak naprawdę nie obchodzi, skąd pochodzi wstrzykiwany obiekt.

Wiktor Zychla
źródło
3

Jest jeden przypadek, w którym wzór Singleton i DI / IoC przecinają się - wstrzyknięcie Singleton.

Większość szkieletów DI można skonfigurować tak, aby tworzyły pojedyncze wystąpienie wstrzykiwanego obiektu. Każdy obiekt konsumenta, który zażąda wystąpienia takiego obiektu, otrzyma to samo pojedyncze wystąpienie. Ta instancja jest z definicji singletonem. To tyle, jeśli chodzi o nakładanie się koncepcji.

Dave
źródło
2

Pomyłka polega na tym, że dwa pojęcia zostały skonfliktowane: singleton i statyczny akcesorium / brama do instancji singletonu.

Jak słusznie zidentyfikowałeś, twój kolega sugeruje, aby wstrzykiwać zależność, a nie uzyskiwać do niej bezpośredni dostęp Singleton.Instance(brama statyczna).

Powodem tego, że tak naprawdę nie ma to nic wspólnego ze wzorem singletonu, jest to, że ta sama koncepcja DI stosuje się w równym stopniu do tworzenia instancji obiektu niebędącego singletonem new Foo(). Zależność byłaby wprowadzana niezależnie od tego, czy jest to implementacja singleton.

Sójka
źródło