94 lines
4.2 KiB
Markdown
94 lines
4.2 KiB
Markdown
---
|
||
aliases:
|
||
- ISP
|
||
tags:
|
||
- maturity/🌱
|
||
date: 2024-09-27
|
||
---
|
||
Принцип разделения интерфейсов (Interface Segregation Principle, ISP) гласит: ==лучше создать несколько специализированных интерфейсов, чем один универсальный,== который заставляет классы реализовывать методы, не относящиеся к их функциональности. Каждый интерфейс должен описывать только те действия, которые действительно нужны конкретному клиенту. Этот принцип помогает избежать ненужной связанности и упрощает поддержку кода.
|
||
|
||
**Для реализации ISP следует:**
|
||
- Создавать узкоспециализированные интерфейсы, соответствующие конкретным задачам.
|
||
- Избегать универсальных интерфейсов с множеством методов, которые могут быть неактуальны для некоторых реализаций.
|
||
- Делить интерфейсы на логически связанные группы методов.
|
||
|
||
**Преимущества соблюдения ISP**
|
||
1. **Снижение связанности:** Реализации зависят только от методов, которые они используют.
|
||
2. **Повышенная гибкость:** Интерфейсы можно изменять или добавлять новые без влияния на классы, которым эти изменения не нужны.
|
||
3. **Упрощение тестирования:** Тестировать реализацию узких интерфейсов проще, так как они охватывают только необходимый функционал.
|
||
4. **Улучшенная читаемость:** Логически разделенные интерфейсы делают код более понятным и структурированным.
|
||
## Пример нарушения ISP
|
||
Рассмотрим интерфейс `Worker`, который описывает как работу, так и прием пищи:
|
||
|
||
```java
|
||
public interface Worker {
|
||
void work();
|
||
void eat();
|
||
}
|
||
|
||
public class RobotWorker implements Worker {
|
||
@Override
|
||
public void work() {
|
||
// Робот работает
|
||
}
|
||
|
||
@Override
|
||
public void eat() {
|
||
// Робот не ест — нарушение ISP
|
||
throw new UnsupportedOperationException("Robots do not eat");
|
||
}
|
||
}
|
||
|
||
```
|
||
|
||
Класс `RobotWorker` вынужден реализовывать метод `eat`, который ему не нужен. Это нарушение ISP, так как интерфейс содержит лишние методы, не применимые ко всем клиентам.
|
||
|
||
Разделим интерфейс на два более специализированных:
|
||
|
||
```java
|
||
public interface Worker {
|
||
void work();
|
||
}
|
||
|
||
public interface Eater {
|
||
void eat();
|
||
}
|
||
|
||
```
|
||
|
||
Теперь каждый класс реализует только те интерфейсы, которые ему нужны:
|
||
|
||
```java
|
||
public class HumanWorker implements Worker, Eater {
|
||
@Override
|
||
public void work() {
|
||
// Человек работает
|
||
}
|
||
|
||
@Override
|
||
public void eat() {
|
||
// Человек ест
|
||
}
|
||
}
|
||
|
||
public class RobotWorker implements Worker {
|
||
@Override
|
||
public void work() {
|
||
// Робот работает
|
||
}
|
||
}
|
||
|
||
```
|
||
***
|
||
## Мета информация
|
||
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
|
||
**Родитель**:: [[SOLID]]
|
||
**Источник**::
|
||
**Создана**:: [[2024-09-27]]
|
||
**Автор**::
|
||
### Дополнительные материалы
|
||
-
|
||
|
||
### Дочерние заметки
|
||
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
|