Я пытаюсь улучшить 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();
m_Service2 = container.Resolve();
m_Service3 = container.Resolve();
}
//approach 3
public delegate Processor Factory();
}
Я думаю, какой здесь должен быть обычный подход. Мы можем оставить конструктор с 3 параметрами, но если мы создаем приложение с использованием autofac (например), скорее всего, он будет редко использоваться, кроме как путем разрешения типов из некоторого экземпляра контейнера, такого как
Processor proc = new Processor(
container.Resolve(),
container.Resolve(),
container.Resolve());
, поэтому я думаю, может быть, подход 2 лучше, когда мы зависим от нескольких типов из контейнера. В любом случае нам нужно будет где-то добавить ссылку на autofac, поэтому есть ли причины не делать этого сейчас?
Autofac также предоставляет метод фабрики делегатов
http://code.google.com/p/autofac/wiki/DelegateFactories
var processorFactory = container.Resolve();
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. интерфейс ясен и не перегружен зависимостями, новый класс может быть хорошим кандидатом на повторное использование.
Что вы скажете об этом?