Принцип інверсії залежності від "Програма на інтерфейс, а не реалізація"


12

Я намагаюся зрозуміти, чим принцип інверсії залежності залежить від принципу "програма на інтерфейс, а не на реалізацію".

Я розумію, що означає "Програма на інтерфейс, а не реалізація". Я також розумію, як це дозволяє зробити більш гнучкими та ретельними конструкції.

Але я не розумію, чим принцип інверсії залежності залежить від принципу "Програма до інтерфейсу, а не реалізації".

Я читав про DIP в декількох місцях в Інтернеті, і це не усунуло моєї плутанини. Я досі не бачу, як два принципи відрізняються один від одного. Спасибі за вашу допомогу.

Відповіді:


26

"Програма на інтерфейс" означає, що не залежить від конкретного типу для виконання вашої роботи , але він не визначає, як ви повинні отримати свою залежність.

"Принцип інверсії залежності" говорить, що об'єкт не повинен контролювати створення його залежностей, він повинен просто рекламувати, яка залежність йому потрібна, і дозволити абоненту її надати . Але не визначено, чи має залежність бути конкретним типом чи інтерфейсом.

Я проілюструю відмінності деяким C # кодом.

Наступний приклад залежить від конкретного типу, і він контролює створення власної залежності. З цього не випливає ні "програма на інтерфейс", ні "інверсія залежності":

public class ThingProcessor
{
    MyThing _myThing;

    public ThingProcessor()
    {
        _myThing = new MyThing();
    }

    public void DoSomething()
    {
        _myThing.DoIt();
    }
}

Наступний приклад залежить від інтерфейсу, але він контролює створення власної залежності. З цього випливає "програма на інтерфейс", але не "інверсія залежності":

public class ThingProcessor
{
    IMyThing _myThing;

    public ThingProcessor()
    {
        _myThing = ThingFactory.GiveMeANewMyThing();
    }

    public void DoSomething()
    {
        _myThing.DoIt();
    }
}

Наступний приклад залежить від конкретного типу, але він просить створити його залежність і передати їй. Звідси випливає "інверсія залежності", але не "програма на інтерфейс":

public class ThingProcessor
{
    MyThing _myThing;

    public ThingProcessor(MyThing myThing)
    {
        _myThing = myThing;
    }

    public void DoSomething()
    {
        _myThing.DoIt();
    }
}

Наступний приклад залежить від інтерфейсу, і він просить створити його залежність і передати їй. Звідси випливає як "інверсія залежності", так і "програма до інтерфейсу":

public class ThingProcessor
{
    IMyThing _myThing;

    public ThingProcessor(IMyThing myThing) // using an interface
    {
        _myThing = myThing;
    }

    public void DoSomething()
    {
        _myThing.DoIt();
    }
}

1
Відмінна ілюстрація різниці.
Рорі Хантер

8
Те, про що ви говорите, - це залежна від ін'єкцій. І інверсія залежності та ін'єкція залежності - це дві різні речі.
Ейфорія

1
@Euphoric Я говорю про принцип інверсії залежності, який є абстрактним поняттям, використовуючи Dependency Injection як конкретний приклад реалізації. Я розумію різницю.
Ерік Кінг

1
@EricKing Тоді вам слід чітко сказати, що у вашій відповіді замість того, щоб йти "Принцип інверсії залежності" сказано ... ", що, очевидно, неправильно, якщо ви читаєте мою відповідь.
Ейфорія

1
Я згоден з Ейфоріком. Принцип інверсії залежності говорить, що шари коду вищого рівня повинні залежати від фрагментів коду нижчого рівня, а не навпаки. Наприклад, PrintStreamповинен залежати від інтерфейсу, встановленого ByteOutputStream. Ін'єкційна залежність нічого не згадує про те, хто повинен залежати від того, хто.
Доваль

5

Вони взагалі те саме. Якщо ви читаєте, що таке принцип інверсії залежності і чому це важливо? і Принцип інверсії залежностей , ви зрозумієте два «принципи» говорити в основному про те ж.

  • Модулі високого рівня не повинні залежати від модулів низького рівня. Обидва повинні залежати від абстракцій.
  • Абстракції ніколи не повинні залежати від деталей. Деталі повинні залежати від абстракцій.

Інтерфейс - це абстракція, а реалізація - деталь. Якщо ви заміните їх у попередніх двох операторах, ви отримаєте в основному "код повинен залежати від інтерфейсів, а не від реалізації". І це звучить як те саме.


Це має бути прийнята відповідь, інша відповідь, яка найбільше проголосується, є оманливою
Sameh Deabes

2

Інтерфейси - один із способів реалізації DI. Якщо ви вказали інтерфейс як параметр у методі конструктора класу, ви можете передати будь-який вподобаний вам об’єкт до цього методу конструктора, доки цей об’єкт реалізує інтерфейс параметра конструктора.

Іншими словами, програмування інтерфейсу дозволяє змінити реалізацію цього інтерфейсу. Це те, як ми можемо замінити макетні об'єкти на реальні об'єкти під час тестування одиниць, вказати різних постачальників даних тощо.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.