Вкладные зависимости в методах или в конструкторе?

Инъекционная инъекция кажется хорошей. В общем случае, следует ли вводить зависимости в соответствии с методами, которые их требуют, или они должны быть введены в конструктор класса?

См. примеры ниже, чтобы продемонстрировать два способа введения той же зависимости.

//Inject the dependency into the methods that require ImportantClass
Class Something {

    public Something()
    {
         //empty
    }

    public void A() 
    {
         //do something without x
    }

    public void B(ImportantClass x)
    {
         //do something with x
    }

    public void C(ImportantClass x)
    {
         //do something with x
    }
}

//Inject the dependency into the constructor once
Class Something {
    private ImportantClass _x
    public Something(ImportantClass x)
    {
         this._x = x;
    }

    public void A() 
    {
         //do something without x
    }

    public void B()
    {
         //do something with this._x
    }

    public void C()
    {
         //do something with this._x
    }

}

Ответы

Ответ 1

Основным преимуществом инъекции конструктора является то, что он позволяет отмечать ваши поля окончательными. Например:

class Foo {
    private final Bar _bar;

    Foo(Bar bar) {
        _bar=bar;
    }
}

На следующей странице есть отличный список про и con: Лучшие практики Guice:

Ввод метода

  • + Не вводить поле
  • + Единственное, что работает для некоторых странных случаев края

Ввод конструктора

  • + Поля могут быть окончательными!
  • + Инъекция не может быть пропущена.
  • + Легко видеть зависимости с первого взгляда.
  • + Это то, о чем идея построения - это
  • - Нет дополнительных инъекций
  • - Бесполезно, если библиотека DI не может выполнять сам экземпляр
  • - Подклассы должны "знать о" инъекциях, необходимых их суперклассам
  • - Менее удобно для тестов, которые только "заботятся" о одном из параметров

Ответ 2

Не вставляя зависимость для каждого метода, вы вынуждаете каждого вызывающего пользователя знать или получать зависимость.

Кроме того, с точки зрения инструментария доступно много доступных фреймворков (по крайней мере, в .NET), которые позволяют или делают инъекцию конструктора намного проще. Это не должно влиять на решение, но делает его гораздо более привлекательным.

Удачи.

Ответ 3

Если вы вводите во время методов, чем вы не различаете поведенческую абстракцию от конкретных зависимостей. Это большой нет нет:). Вы хотите зависеть от абстракций, чтобы не сочетаться с зависимостями зависимостей ваших классов.,

Поскольку ваш конструктор не будет присутствовать в каком-либо интерфейсе, который поддерживает ваш конкретный класс, чем вы не связываетесь с этой зависимостью. Но вызов метода будет иметь эту проблему.

Вот хорошая статья об этом типике:

http://chrisdonnan.com/blog/2007/05/20/conquest-through-extreme-composition-glue-part-2/

Ответ 4

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

Ответ 5

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

public interface IFoo
{
   void Do();
}

public class IFoo DefaultFoo : IFoo
{
   public void Do()
   {
   }
}

public class UsesFoo
{
   private IFoo foo;
   public IFoo Foo
   {
       set { this.foo = value; }
   }

   public UsesFoo()
   {
      this.Foo = new DefaultFoo();
   }

   public UsesFoo( IFoo foo )
   {
      this.Foo = foo;
   }

   public void DoFoo()
   {
      this.Foo.Do();
   }
}

Ответ 6

Я имею тенденцию использовать второй метод, но тогда это потому, что я стараюсь сделать мои pojos beans, что означает, что конструктор аргументов 0 полезен.