Добавить в корзинуПозвонить
Найти в Дзене
Записки о Java

Принципы SOLID в Java 11: основа чистого и поддерживаемого кода

В мире разработки программного обеспечения принципы SOLID уже давно стали не просто рекомендациями, а фундаментом для создания гибких, масштабируемых и легко тестируемых приложений. Особенно актуальны они в экосистеме Java, где объектно-ориентированное проектирование играет ключевую роль. В этой статье мы подробно рассмотрим каждый из пяти принципов SOLID с примерами на Java. SOLID — это аббревиатура, включающая пять основных принципов объектно-ориентированного проектирования и программирования: Разберём каждый из них подробно. Класс должен иметь только одну причину для изменения. Другими словами, каждый класс должен решать только одну задачу. Если у класса появляется вторая обязанность, его стоит разделить. Здесь OrderProcessor отвечает за три разных задачи: обработку заказа, сохранение данных и отправку уведомлений. Теперь каждый класс имеет одну зону ответственности. Программные сущности (классы, модули, функции и т.д.) должны быть открыты для расширения, но закрыты для модификации.
Оглавление
Рисунок: принципы SOLID
Рисунок: принципы SOLID

Принципы SOLID в Java 11: основа чистого и поддерживаемого кода

В мире разработки программного обеспечения принципы SOLID уже давно стали не просто рекомендациями, а фундаментом для создания гибких, масштабируемых и легко тестируемых приложений. Особенно актуальны они в экосистеме Java, где объектно-ориентированное проектирование играет ключевую роль. В этой статье мы подробно рассмотрим каждый из пяти принципов SOLID с примерами на Java.

Что такое SOLID?

SOLID — это аббревиатура, включающая пять основных принципов объектно-ориентированного проектирования и программирования:

  1. SSingle Responsibility Principle (Принцип единственной ответственности)
  2. OOpen/Closed Principle (Принцип открытости/закрытости)
  3. LLiskov Substitution Principle (Принцип подстановки Барбары Лисков)
  4. IInterface Segregation Principle (Принцип разделения интерфейсов)
  5. DDependency Inversion Principle (Принцип инверсии зависимостей)

Разберём каждый из них подробно.

1. Single Responsibility Principle (SRP)

Класс должен иметь только одну причину для изменения.

Другими словами, каждый класс должен решать только одну задачу. Если у класса появляется вторая обязанность, его стоит разделить.

Пример нарушения:

Рисунок: пример нарушения принципа single responsible
Рисунок: пример нарушения принципа single responsible

Здесь OrderProcessor отвечает за три разных задачи: обработку заказа, сохранение данных и отправку уведомлений.

Исправленный вариант:

Рисунок: пример класса соблюдающего принцип single responsible
Рисунок: пример класса соблюдающего принцип single responsible

Теперь каждый класс имеет одну зону ответственности.

2. Open/Closed Principle (OCP)

Программные сущности (классы, модули, функции и т.д.) должны быть открыты для расширения, но закрыты для модификации.

Это означает, что поведение системы можно расширять без изменения уже написанного кода — например, через наследование или композицию.

Пример нарушения:

Рисунок: класс, нарушающий принцип Open-Closed
Рисунок: класс, нарушающий принцип Open-Closed

Добавление новой фигуры потребует изменения AreaCalculator.

Исправленный вариант:

Рисунок: пример класса, соблюдающий принцип Open-Closed, часть 1
Рисунок: пример класса, соблюдающий принцип Open-Closed, часть 1
Рисунок: пример класса, соблюдающий принцип Open-Closed, часть 2
Рисунок: пример класса, соблюдающий принцип Open-Closed, часть 2

Теперь добавление новой фигуры не требует изменения AreaCalculator.

3. Liskov Substitution Principle (LSP)

Объекты в программе должны быть заменяемы их подтипами без изменения корректности работы программы.

Если класс B наследуется от A, то объекты B должны вести себя так же, как и объекты A.

Пример нарушения:

Рисунок: DTO Rectangle
Рисунок: DTO Rectangle
Рисунок: DTO Square
Рисунок: DTO Square

Если использовать Square там, где ожидается Rectangle, поведение может быть непредсказуемым.

Решение:

Избегайте наследования в таких случаях. Используйте композицию или отдельные интерфейсы:

Рисунок: следование принципу Liskov Substitution
Рисунок: следование принципу Liskov Substitution

4. Interface Segregation Principle (ISP)

Клиенты не должны зависеть от интерфейсов, которые они не используют.

Лучше иметь много узкоспециализированных интерфейсов, чем один «жирный».

Пример нарушения:

Рисунок: пример нарушения принципа Interface Segregation
Рисунок: пример нарушения принципа Interface Segregation

Исправленный вариант:

Рисунок: следование принципу Interface Segregation
Рисунок: следование принципу Interface Segregation

Теперь RobotWorker не зависит от методов, которые ему не нужны

5. Dependency Inversion Principle (DIP)

Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракций.
Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

Это основа инверсии управления (IoC) и внедрения зависимостей (DI).

Пример нарушения:

Рисунок: пример нарушения принципа Dependency Inversion
Рисунок: пример нарушения принципа Dependency Inversion

Исправленный вариант:

Рисунок: пример следование принципу Dependency Inversion
Рисунок: пример следование принципу Dependency Inversion

Теперь Notification зависит от абстракции (MessageService), а не от конкретной реализации.

Заключение

Принципы SOLID — это не догма, а практические рекомендации, которые помогают писать код, который легко читать, тестировать и поддерживать. В Java, их применение особенно важно при разработке enterprise-приложений, где требования часто меняются, а стабильность критична.

Следуя SOLID, вы не только улучшаете архитектуру своего кода, но и делаете его более гибким к будущим изменениям — а это, пожалуй, главная цель любого профессионального разработчика.

Примеры, рассмотренные в статье, можно найти по адресу:
https://github.com/ShkrylAndrei/blog_yandex/tree/main/src/main/java/info/solid