Definicja
Reguła ta oznajmia nam, aby nie tworzyć interfejsów z metodami, których nie używa klasa. Interfejsy powinny być jak najmniejsze i konkretne klasy nie powinny implementować metod których nie potrzebują. Nie powinno dojść do sytuacji, gdy któraś z klas pochodnych nie wykorzystuje zaimplementowanej w interfejsie metody. Wyobraźmy sobie, że mamy interfejs, który jest używany w kilkunastu innych projektach, jednak w każdym projekcie używana jest tylko jedna metoda tego interfejsu. Gdy zajdzie potrzeba zmiany tego interfejsu spotkamy się z problemem ingerowania w każdy projekt. Nie powinniśmy zmuszać klasy do implementowania metod, których nie potrzebuje. Lepiej zdefiniować większą liczbę małych i lekkich interfejsów
Przykład programu przed wdrożeniem LSP
public interface Document {
void open();
void save();
void print();
void sendViaEmail();
}
public class PDFDocument implements Document{
@Override
public void open() {
System.out.println("Logic for opening a PDF document");
}
@Override
public void save() {
System.out.println("Logic for saving a PDF document");
}
@Override
public void print() {
System.out.println("Logic for printing a PDF document");
}
@Override
public void sendViaEmail() {
System.out.println("Logic for sending a PDF document via email");
}
}
public class WordDocument implements Document{
@Override
public void open() {
System.out.println("Logic for opening a Word document");
}
@Override
public void save() {
System.out.println("Logic for saving a Word document");
}
@Override
public void print() {
System.out.println("Logic for printing a Word document");
}
@Override
public void sendViaEmail() {
System.out.println("Logic for sending a Word document via email");
}
}
Aby zastosować zasadę segregacji interfejsu, musimy podzielić interfejs
Document na mniejsze, bardziej szczegółowe interfejsy. Pozwala to klasom implementować tylko to, czego potrzebują. Zobaczmy, jak możemy to zrobić:
Kod po zastosowaniu zasady ISP
public interface OpenSave {
void open();
void save();
}
public interface Print {
void print();
}
public interface SendViaEmail {
void sendViaEmail();
}
public class PDFDocument implements OpenSave, Print{
@Override
public void open() {
System.out.println("Logic for opening a PDF document");
}
@Override
public void save() {
System.out.println("Logic for saving a PDF document");
}
@Override
public void print() {
System.out.println("Logic for printing a PDF document");
}
}
public class WordDocument implements OpenSave, SendViaEmail{
@Override
public void open() {
System.out.println("Logic for opening a Word document");
}
@Override
public void save() {
System.out.println("Logic for saving a Word document");
}
@Override
public void sendViaEmail() {
System.out.println("Logic for sending a Word document via email");
}
}
Podsumowanie
Dzięki tej nowej strukturze każda klasa implementuje tylko interfejsy, których potrzebuje, unikając konieczności implementowania nieistotnych metod. Dzięki temu nasz kod jest bardziej przejrzysty i łatwiejszy w utrzymaniu
