„Program do interfejsu” oznacza, że nie zależy od konkretnego rodzaju pracy , ale nie określa, w jaki sposób należy uzyskać zależność.
„Zasada inwersji zależności” mówi, że obiekt nie powinien kontrolować tworzenia swoich zależności, powinien po prostu ogłosić, jakiej zależności potrzebuje i pozwolić, aby osoba dzwoniąca podała ją . Ale nie określa, czy zależność powinna być konkretnym typem, czy interfejsem.
Zilustruję różnice za pomocą kodu C #.
Poniższy przykład zależy od konkretnego typu i kontroluje tworzenie własnej zależności. Wynika ani „programu do interfejsu” ani „zależność inwersji”:
public class ThingProcessor
{
MyThing _myThing;
public ThingProcessor()
{
_myThing = new MyThing();
}
public void DoSomething()
{
_myThing.DoIt();
}
}
Poniższy przykład zależy od interfejsu, ale kontroluje tworzenie własnej zależności. Wynika to z „program do interfejsu”, ale nie „inwersja zależności”:
public class ThingProcessor
{
IMyThing _myThing;
public ThingProcessor()
{
_myThing = ThingFactory.GiveMeANewMyThing();
}
public void DoSomething()
{
_myThing.DoIt();
}
}
Poniższy przykład zależy od konkretnego typu, ale prosi o utworzenie i przekazanie zależności. Wynika to z „odwrócenia zależności”, ale nie „program do interfejsu”:
public class ThingProcessor
{
MyThing _myThing;
public ThingProcessor(MyThing myThing)
{
_myThing = myThing;
}
public void DoSomething()
{
_myThing.DoIt();
}
}
Poniższy przykład zależy od interfejsu i prosi o utworzenie i przekazanie zależności. Wynika zarówno z „inwersji zależności”, jak i „programu do interfejsu”:
public class ThingProcessor
{
IMyThing _myThing;
public ThingProcessor(IMyThing myThing) // using an interface
{
_myThing = myThing;
}
public void DoSomething()
{
_myThing.DoIt();
}
}
PrintStream
Powinien zależeć od interfejsu ustanowionego przezByteOutputStream
. Wstrzykiwanie zależności nie wspomina nic o tym, kto powinien zależeć od kogo.Są ogólnie takie same. Jeśli przeczytasz Czym jest zasada inwersji zależności i dlaczego jest ważna? i Zasadę Inwersji Zależności , uświadomicie sobie, że dwie „zasady” mówią w zasadzie o tym samym.
Interfejs to abstrakcja, a implementacja to szczegół. Jeśli podmienisz je w poprzednich dwóch instrukcjach, otrzymasz w zasadzie „kod powinien zależeć od interfejsów, a nie implementacji”. I to dla mnie brzmi tak samo.
źródło
Interfejsy są jednym ze sposobów implementacji DI. Jeśli podasz interfejs jako parametr w metodzie konstruktora klasy, możesz przekazać dowolny obiekt tej metodzie konstruktora, o ile obiekt ten implementuje interfejs parametru konstruktora.
Innymi słowy, programowanie interfejsu pozwala zmienić implementację tego interfejsu. W ten sposób jesteśmy w stanie zastąpić fałszywe obiekty rzeczywistymi obiektami podczas testów jednostkowych, określić różnych dostawców danych i tak dalej.
źródło