OOD с использованием контейнеров IoC - как конструировать зависимые объекты?

Я пытаюсь улучшить 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. интерфейс ясен и не перегружен зависимостями, новый класс может быть хорошим кандидатом на повторное использование.

Что вы скажете об этом?

5
задан Valentin Kuzub 20 August 2011 в 12:49
поделиться