Я пытаюсь стать лучше с IoC, DI и OOD для лучшей тестируемости и более слабой связи.
Поэтому, когда мы разрабатываем классы с интенсивным использованием IoC и DI, мы можем в конечном итоге получить классы с несколькими зависимостями, например
class Processor
{
private IService1 m_Service1;
private IService2 m_Service2;
private IService3 m_Service3;
//approach 1
public Processor(IService1 service1, IService2 service2, IService3 service3)
{
m_Service1 = service1;
m_Service2 = service2;
m_Service3 = service3;
}
//approach 2
public Processor(IContainer container)
{
m_Service1 = container.Resolve<IService1>();
m_Service2 = container.Resolve<IService2>();
m_Service3 = container.Resolve<IService3>();
}
//approach 3
public delegate Processor Factory();
}
Я думаю, что здесь должен быть обычный подход. Мы можем оставить конструктор с 3 параметрами, но если мы создаем приложение, используя autofac (например), скорее всего, оно будет редко использоваться, кроме как путем разрешения типов из некоторого экземпляра контейнера, такого как
Processor proc = new Processor(
container.Resolve<IService1>(),
container.Resolve<IService2>(),
container.Resolve<IService3>());
поэтому я думаю, что, возможно, подход 2 лучше, когда мы зависим от нескольких типов из контейнера. В любом случае нам нужно будет где-нибудь добавить ссылку на autofac, поэтому есть ли причины не делать это сейчас?
Autofac также предоставляет метод фабрики делегатов
http://code.google.com/p/autofac/wiki/DelegateFactories
var processorFactory = container.Resolve<Processor.Factory>();
Processor processor = processorFactory.Invoke();
Таким образом, у нас также есть подход 3 - мы не будем использовать конструкторы для создания экземпляров нашего класса, вместо этого мы будем вызывать разрешенный делегат из контейнера, и это разрешит нам зависимости.
Поскольку я довольно новичок в IoC, трудно сказать, когда нам следует использовать 1,2,3. У них есть свои преимущества и недостатки.
Я думаю, что в общем случае, если у класса есть 1 зависимость, мы, вероятно, всегда можем использовать подход 1 ... кроме этого, я действительно не уверен, что выбрать и когда.
ОБНОВЛЕНИЕ Я читал об анти-паттерне сервисного локатора, но у меня есть 4-й (или настоящий 3-й подход)
он близок к ServiceLocator, за исключением его, мы передаем объект, который выглядит следующим образом
public class ServiceLocatorObject
{
private IService1 m_Service1;
private IService2 m_Service2;
private IService3 m_Service3;
public IService1 Service1 {get {return m_Service1;}}
public IService2 Service2 {get {return m_Service2;}}
public IService3 Service3 {get {return m_Service3;}}
public ServiceLocatorObject(IService1 service1, IService2 service2, IService3 service3)
{
m_Service1 = service1;
m_Service2 = service2;
m_Service3 = service3;
}
}
А теперь мы создаем
//approach 4
public Processor(ServiceLocatorObject servicesToUse)
{
m_Services = servicesToUse;
}
Теперь мы отсоединили наш класс от реализаций сервисов, и стало ясно, какие реальные зависимости ему нужны (если мы предположим, что требуются все сервисы, доступные для переданного объекта), потому что мы не передаем контейнер, который может содержать 100 реализаций. И этот объект может даже использоваться повторно, если в нашем приложении может потребоваться эта комбинация из трех сервисов. Поэтому мы используем конструктор DI, а не шаблон ServiceLocator. интерфейс понятен и не перегружен зависимостями, новый класс может быть хорошим кандидатом для повторного использования.
Что бы вы сказали об этом?