Инъекция зависимостей и синглтон. Это две совершенно разные концепции?

17

Я слышал об использовании инъекции зависимостей через Singleton для моего коллеги. Я до сих пор не могу разобрать, если это два ортогональных шаблона, которые можно заменить друг на друга? Или DI способ сделать тестируемый паттерн Singleton?

Пожалуйста, взгляните на следующий фрагмент кода.

    IMathFace obj = Singleton.Instance;

    SingletonConsumer singConsumer = new SingletonConsumer(obj);

    singConsumer.ConsumerAdd(10,20);

SingletonConsumerПринимает параметр типа IMathFace. Вместо внутреннего доступа к одноэлементному классу SingletonConsumerбудет получен экземпляр синглтона, переданный вызывающей стороной. Является ли это хорошим примером использования одноэлементного класса посредством внедрения зависимостей?

logeeks
источник
Подскажите, пожалуйста, как DI может заменить синглтон?
7
Синглтон - это шаблон дизайна. DI / IoC - это техника.
Дэйв
2
Я не могу заменить синглтон больше, чем банан может заменить карбюратор. Это совершенно разные понятия.
Дэйв
так что мой пример действителен.
1
Да, но это может произойти за счет инкапсуляции (что также верно для не-синглтона), см .: stackoverflow.com/questions/1005473/…

Ответы:

17

Я думаю, он имел в виду, что вы должны использовать внедрение зависимостей для внедрения одного экземпляра службы, вместо использования классической реализации Singleton со статическим средством доступа MySingleton.Instance.

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

В классической одноэлементной реализации весь ваш код зависит от того, является ли этот сервис одноэлементным. Вы в основном жестко закодируете это предположение в потреблении кода при каждом использовании MySingleton.Instance.

С другой стороны, с помощью DI вы получаете экземпляр сервиса, передаваемый в ваш конструктор, и сохраняете его. То, что существует только один экземпляр этого сервиса, является деталью реализации. Вы можете легко изменить его, чтобы присвоить потребляющему коду другой экземпляр. Таким образом, у вас есть некоторый класс / интерфейс, который реализуется одним экземпляром, вместо того, чтобы принудительно использовать только один экземпляр.

Это полезно, например, если вы хотите использовать фиктивную реализацию сервиса для тестирования или если разные части программы нуждаются в разных конфигурациях этого сервиса.

CodesInChaos
источник
4

Да ты прав. Вместо того, чтобы обращаться к объекту через синглтон, вы передаете ссылку на него, таким образом, вы используете инъекцию конструктора.

Другие указывают на то, что эти понятия не связаны. Использование одноэлементного экземпляра не является чем-то особенным, так как объект, который вы вводите, на самом деле не заботится о том, откуда поступает этот объект.

Виктор Зихла
источник
3

Существует один случай, когда паттерн Синглтон и DI / IoC пересекаются - инъекция Синглтона.

Большинство структур DI могут быть настроены на создание одного экземпляра внедренного объекта. Любой потребительский объект, который запрашивает экземпляр такого объекта, получит один и тот же экземпляр. Этот экземпляр по определению является синглтоном. Вот и все, что связано с концепцией.

Дейв
источник
2

Путаница заключается в том, что две концепции были объединены: синглтон и статический доступ / шлюз к экземпляру синглтона.

Как вы правильно определили, ваш коллега предлагает вводить зависимость, а не напрямую Singleton.Instance (статический шлюз).

Причина, по которой это не имеет ничего общего с одноэлементным шаблоном, заключается в том, что та же концепция DI в равной степени применима к созданию экземпляра не-одиночного объекта new Foo(). Зависимость будет введена независимо от того, является ли она одноэлементной реализацией.

сойка
источник