Подтвердить что ты не робот

Я запутался в абстракциях интерфейса при использовании IoC

Недавно я пытался изучить IoC и задать пару вопросов на основе следующего кода:

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

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

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


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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

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

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

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

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