Czwarta z zasad SOLID to zasada segregacji interfejsów – Interface Segregation Principle. Mówi ona o tym, że żaden klient (klasa) nie powinien być zmuszany do polegania na interfejsach, z których nie korzysta. Kilka mniejszych, dedykowanych interfejsów jest lepsze niż jeden zbyt ogólny. Nie powinniśmy stosować tych tzw. fat interfaces – zawierających deklaracje metod, które niekoniecznie powinny być implementowane przez każdego z użytkowników. Jako przykład złamania zasady ISP niech posłuży kwestia organizacji spotkań biznesowych lub w ogóle wydarzeń publicznych. Stwórzmy więc interfejs Tasks z zadaniami do rozdysponowania umieszczonymi w metodach provideFood, provideEquipment, decorateRoom.
Tasks.java
package organizer.event;
public interface Tasks {
void provideFood();
void decorateRoom();
void provideEquipment();
}
FoodManager.java
package organizer.event;
public class FoodManager implements Tasks{
@Override
public void provideFood() {
//provide wide range of snacks and dishes
}
@Override
public void decorateRoom() {
throw new TypeOfWorkNotSupportedException();
}
@Override
public void provideEquipment() {
throw new TypeOfWorkNotSupportedException();
}
}
DecoratingManager.java
package organizer.event;
public class DecoratingManager implements Tasks{
@Override
public void provideFood() {
throw new TypeOfWorkNotSupportedException();
}
@Override
public void decorateRoom() {
//provide flowers,decorations etc.
}
@Override
public void provideEquipment() {
throw new TypeOfWorkNotSupportedException();
}
}
TechnicalManager.java
package organizer.event;
public class TechnicalManager implements Tasks{
@Override
public void provideFood() {
throw new TypeOfWorkNotSupportedException();
}
@Override
public void decorateRoom() {
throw new TypeOfWorkNotSupportedException();
}
@Override
public void provideEquipment() {
//provide technical equipment of the room e.g. computer with projector, sound system etc.
}
}
Interfejs Tasks implementują klasy odpowiedzialne za poszczególne zadania. Jednak żadna z tych klasa nie potrzebuje implementować wszystkich metod w interfejsie. W przypadku zmiany interfejsu np. dodania metody od zapewnienia oprawy muzycznej wydarzenia, potrzebne będzie dodanie implementacji tej metody we wszystkich klasach implementujących dany interfejs, a więc zmiany będą obejmować wiele miejsc w naszym kodzie. Aby temu zapobiec rozbijmy interfejs Tasks na poszczególne interfejsy dedykowane odpowiednim zadaniom: FoodTasks, DecorationTasks, EquipmentTasks. Każda klasa niech implementuje interfejs związany z zadaniem, którym się zajmuje. Zachowana zostanie więc zasada segregacji interfejsów – ISP. W ten sposób w przyszłości zmiany dotyczące np. wyboru menu lub zmian charakteru dekoracji obejmą jeden interfejs i jedną klasę, która go implementuje – mamy tutaj do czynienia także z zasadą jednej odpowiedzialności – SRP.
FoodTasks.java
package organizer.event;
public interface FoodTasks {
void provideFood();
}
DecorationTasks.java
package organizer.event;
public interface DecorationTasks {
void decorateRoom();
}
EquipmentTasks.java
package organizer.event;
public interface EquipmentTasks {
void provideEquipment();
}
FoodManager.java
package organizer.event;
public class FoodManager implements FoodTasks {
@Override
public void provideFood() {
//provide wide range of snacks and dishes
}
}
DecorationManager.java
package organizer.event;
public class DecoratingManager implements DecorationTasks {
@Override
public void decorateRoom() {
//provide flowers,decorations etc.
}
}
TechnicalManager.java
package organizer.event;
public class TechnicalManager implements EquipmentTasks {
@Override
public void provideEquipment() {
//provide technical equipment of the room e.g. computer with projector, sound system etc.
}
}
PODSUMOWANIE
Dzięki zastosowaniu zasady segregacji interfejsów – ISP, nasz kod jest odpowiednio posegregowany, a tym samym łatwiejszy do zarządzania i utrzymywania. Ponadto osiągamy tzw. „high cohesion” czyli wysoką spójność kodu. Zasada ta jest powiązana również z zasadą Single Responsibility Principle oraz Liskov Substitution Principle omawianymi w poprzednich wpisach.