DIP mówi o tym, że moduły wysokopoziomowe nie powinny być zależne od modułów niskopoziomowych, ich zależności powinny wynikać z abstrakcji (stosowanie interfejsów i klas abstrakcyjnych). Ponadto abstrakcje nie powinny zależeć od szczegółów tylko odwrotnie, szczegóły powinny zależeć od abstrakcji.
Mamy klasę Manager, która jest klasą na wysokim poziomie, oraz klasę niskiego poziomu zwaną Sms. I teraz musimy dodać nowy moduł do naszej aplikacji, aby modelować zmiany w strukturze firmy determinowane nowym sposobem wysyłania wiadomości. W tym celu stworzyliśmy nową klasę Email. Załóżmy, że klasa Manager jest dość złożona i zawiera bardzo złożoną logikę i teraz musimy to zmienić, aby wprowadzić obsługę nowej klasy Email.
ZŁY KOD
public class Sms
{
public void Send()
{
// ....sending
}
}
public class Manager
{
Sms _sms;
public void SetSms(Sms sms)
{
_sms = sms;
}
public void Manage()
{
sms.Send();
}
}
public class Email
{
public void Send()
{
//.... sending
}
}
Jakie mamy wady:
– musimy zmienić klasę Manager, pamiętamy, że jest to klasa złożona, a wprowadzenie zmian będzie wymagało czasu i wysiłku.
– może to mieć wpływ na niektóre bieżące funkcje klasy Manager.
– testy jednostkowe należy powtórzyć.
DOBRY KOD
public interface ISend
{
void Send();
}
public class Sms :ISend
{
public void Send()
{
// ....sending
}
}
public class Email : ISend
{
public void Send()
{
//.... sending
}
}
public class Fax : ISend
{
public void Send()
{
//.... sending
}
}
public class Manager
{
ISend _send;
public void SetSms(ISend send)
{
_send = send;
}
public void Manage()
{
_send.Send();
}
}
Zastosowanie tej zasady oznacza, że klasy wysokiego poziomu nie działają bezpośrednio z klasami niskiego poziomu, używają interfejsów jako warstwy abstrakcyjnej.