Каковы основные принципы проектирования по шаблону внедрения зависимостей - PullRequest
3 голосов
/ 15 июля 2010

Я новичок в идее паттерна DI и у меня есть некоторые базовые сомнения в дизайне. Я использую блоки приложений Unity 2.0 в качестве моей DI-фреймворка.

На вопросы:

  1. Скажем, у меня есть интерфейс для устройств HW с именем IDevice. И какой-то HW слушатель, который получает такой IDevice. Теперь предположим, что у вас есть несколько устройств HW, которые реализуют IDevice и несколько слушателей. Вы должны указать для каждого слушателя, какое устройство вводить. Вы не можете просто привязать одно устройство к тому интерфейсу, который вам нужен, например, множественное сопоставление.

хорошо, одно из возможных решений - создать еще один уровень абстракции для каждого фактического устройства. как

public interface IActualDevice : IDevice
{}

public ActualDevice : IActualDevice
{}

public SimulatedActualDevice : IActualDevice
{}

public OtherAcualDevice: IOtherAcualDevice
{}

тогда можно было бы создать такое отображение:

container.RegisterType<IActualDevice, ActualDevice>()

или если HW отсутствует:

container.RegisterType<IActualDevice, SimulatedActualDevice>()

так что вы скажете, это хороший дизайн?

  1. Шаблон DI дает нам хороший механизм создания объектов.

А как насчет клея, а как насчет подписки на события между объектами?

не думаете ли вы, что он отсутствует или, что лучше, мне не хватает какой-то функции Unity, которая его поддерживает.

Adiel.

Ответы [ 2 ]

3 голосов
/ 15 июля 2010

Нет необходимости вводить интерфейсы маркеров для работы вашего DI-контейнера - это будет Leaky Abstraction .

С Unity вы можете настроить каждый слушатель с его собственной реализацией IDevice, напримерthis:

container.RegisterType<IDevice, ActualDevice>("actual");
container.RegisterType<IDevice, OtherActualDevice>("otherActual");

container.RegisterType<IListener, Listener1>("listener1",
    new InjectionConstructor(
        new ResolvedParameter<IDevice>("actual")));
container.RegisterType<IListener, Listener2>("listener2",
    new InjectionConstructor(
        new ResolvedParameter<IDevice>("otherActual")));

Теперь вы можете разрешить слушателей следующим образом:

var listener1 = container.Resolve<IListener>("listener1");
var listener2 = container.Resolve<IListener>("listener2");

Как правило, основными шаблонами DI являются Constructor Injection и Абстрактная фабрика .Большинство других вещей следуют из этих двух.См. этот ответ , чтобы узнать больше моделей и принципов DI.

0 голосов
/ 15 июля 2010

1) Это абсолютно плохая идея, потому что интерфейсы предназначены для сокрытия деталей реализации.Повсеместно используйте тип IDevice и введите эту зависимость вручную

IDevice d;

if(a == 1)
{
   d = container.Resolve<SimulatedActualDevice>()
}
else
{
   d = container.Resolve<ActualDevice>()
}

User user = container.Resolve<IUser>();
user.Device = d;

Если вы не хотите использовать имена классов реализации в коде, используйте именованные регистрации:

IDevice d;

if(a == 1)
{
   d = container.Resolve<IDevice>("Simulated")
}
else
{
   d = container.Resolve<IDevice>("Actual")
}

User user = container.Resolve<IUser>();
user.Device = d;

2) Подписка на событияОбъекты являются частью инициализации объекта, но не частью создания.Unity просто инкапсулирует «новые» операторы.Создавайте подписки в конструкторах или на специальных фабриках, как вы делали до использования DI-контейнера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...