Я запутался по поводу абстракций интерфейса при использовании IoC - PullRequest
12 голосов
/ 28 февраля 2011

Я недавно пытался изучить IoC, и у меня есть пара вопросов, основанных на следующем коде:

public class WarriorModule : NinjectModule 
{
    public override void Load() 
    {
        Bind<IWeapon>().To<Sword>();
        Bind<Samurai>().ToSelf();
    }
}

У меня проблемы с пониманием новой концепции интерфейсов. Прежде я хотел бы создать такой интерфейс, как IRunnable, реализующий функцию void Run(). С IoC я теперь рассматриваю интерфейс как нечто, отображающее только один конкретный класс. Предполагая, что, как бы я отобразил несколько конкретных классов на интерфейс? Я продолжаю читать, что вы можете сопоставить несколько интерфейсов с одним конкретным классом, но не наоборот (если только здесь не возникает контекстное сопоставление играть).

Предполагая, что интерфейсы отображаются только на один объект, когда мне следует создавать интерфейс, а не привязывать объект к себе? В любом случае вам придется изменить один и тот же фрагмент кода при изменении отображения правильный?


Редактировать: Я отметил ответ, который сделал, потому что он помог мне лично. Оба комментария одинаково информативны.

Ответы [ 2 ]

18 голосов
/ 28 февраля 2011

Хороший контейнер IoC не должен изменять способ использования интерфейсов:

  1. Интерфейс должен быть разработан для компонента, который использует его в качестве зависимости, а не для класса, который его реализует. (принцип сегрегации интерфейса)
  2. Класс может реализовывать несколько интерфейсов. Но это следует делать только в том случае, если эти интерфейсы предназначены для одного и того же вида услуг, так что класс делает только одно. Если интерфейсы предназначены для двух разных вещей, они должны быть реализованы двумя разными классами. (принцип единой ответственности)
  3. Несколько классов могут реализовывать один и тот же интерфейс, если вам нужно несколько стратегий для этого типа сервиса.

Ninject позволяет использовать интерфейсы таким образом, используя две разные концепции:

  1. Условные привязки: если несколько классов реализуют один и тот же интерфейс, вы должны указать, какая реализация используется в каком случае. Это делается с использованием условий:

    Bind<IWeapon>().To<Sword>().When(ctx => TodayIsSunday());

    Bind<IWeapon>().To<Dagger>().When(ctx => !TodayIsSunday());

  2. Несколько интерфейсов: см. Мой пост http://www.planetgeek.ch/2010/12/08/ninject-extension-contextpreservation-explained/

16 голосов
/ 28 февраля 2011

Я недавно обратился к этой теме с более общей точки зрения . Суть в том, что существует тенденция к слабосвязанному коду с переизбытком интерфейсов 1: 1 . Это противоречит принципу Повторно использованные абстракции .

Однако это скорее проблема разработки приложения , чем проблема, связанная с определенными контейнерами DI. Хотя я не знаю Ninject, все другие контейнеры, с которыми я когда-либо работал (Castle Windsor, StructureMap, Spring.NET, Autofac, Unity и даже MEF), могут отображать несколько реализаций в одном интерфейсе. То, как они это делают, немного отличается, но я рассмотрю все из них в части IV моей книги - к сожалению, Ninject не рассматривается в этой книге.

...