digital-garden/dev/architecture/Open Closed Principle.md

107 lines
5.4 KiB
Markdown
Raw Normal View History

2024-09-27 20:25:32 +03:00
---
aliases:
- Open/Closed Principle
- OCP
- Принцип открытости/закрытости
tags:
- maturity/🌱
date: 2024-09-27
---
Классы и модули должны быть **открыты для расширения, но закрыты для модификации**. Это означает, что функциональность можно добавлять без изменения существующего кода. Такой подход позволяет минимизировать риск возникновения ошибок в уже работающей системе при внедрении новых функций. **Принцип открытости/закрытости (Open-Closed Principle, OCP)** является вторым из пяти [[SOLID]]-принципов и способствует созданию гибкой и поддерживаемой архитектуры.
2024-09-27 20:25:32 +03:00
Обычно для реализации принципа используются:
- **Интерфейсы** или **абстрактные классы**, которые задают общую структуру поведения.
- [[Полиморфизм]], позволяющий создавать новые реализации без изменения базового кода.
Следование OCP снижает связанность модулей, делает код проще в тестировании и облегчает внедрение новых функций.
**Преимущества соблюдения OCP:**
1. **Гибкость кода:** Добавление нового функционала не требует изменений существующего кода, что снижает риск ошибок.
2. **Улучшенная тестируемость:** Изолированные реализации проще тестировать независимо друг от друга.
3. **Снижение связанности:** Код становится более модульным, и изменения в одной части системы не затрагивают другие.
4. **Поддерживаемость:** Разработчики могут легко добавлять новые возможности без угрозы сломать существующий функционал.
## Пример нарушения OCP
Рассмотрим класс, который обрабатывает оплату, поддерживая только один способ оплаты через кредитную карту:
```java
public class PaymentProcessor {
public void processPayment(String type, double amount) {
if (type.equals("credit_card")) {
// Логика оплаты через кредитную карту
}
}
}
```
Если требуется добавить поддержку нового способа оплаты, например, PayPal, придется модифицировать метод `processPayment`:
```java
public class PaymentProcessor {
public void processPayment(String type, double amount) {
if (type.equals("credit_card")) {
// Логика оплаты через кредитную карту
} else if (type.equals("paypal")) {
// Логика оплаты через PayPal
}
}
}
```
Такой подход нарушает OCP, так как для добавления нового функционала приходится изменять уже существующий код. Это увеличивает риск ошибок и затрудняет сопровождение.
Используем интерфейсы для реализации разных способов оплаты:
2024-09-27 20:25:32 +03:00
```java
public interface PaymentMethod {
void pay(double amount);
}
public class CreditCardPayment implements PaymentMethod {
@Override
public void pay(double amount) {
// Оплата через кредитную карту
}
}
public class PayPalPayment implements PaymentMethod {
@Override
public void pay(double amount) {
// Оплата через PayPal
}
}
```
Теперь процессор оплаты будет работать с интерфейсом `PaymentMethod`, не завися от конкретных реализаций:
```java
public class PaymentProcessor {
private PaymentMethod paymentMethod;
public PaymentProcessor(PaymentMethod paymentMethod) {
this.paymentMethod = paymentMethod;
}
public void processPayment(double amount) {
paymentMethod.pay(amount);
}
}
```
Для добавления нового способа оплаты достаточно создать новую реализацию `PaymentMethod`, не изменяя код процессора.
2024-09-27 20:25:32 +03:00
***
## Мета информация
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
**Родитель**:: [[SOLID|SOLID]]
**Источник**::
**Создана**:: [[2024-09-27]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->