digital-garden/dev/architecture/Open Closed Principle.md
Struchkov Mark 2c945630a3
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone Build is passing
Обновление и рефакторинг
2024-11-23 21:34:40 +03:00

107 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
aliases:
- Open/Closed Principle
- OCP
- Принцип открытости/закрытости
tags:
- maturity/🌱
date: 2024-09-27
---
Классы и модули должны быть **открыты для расширения, но закрыты для модификации**. Это означает, что функциональность можно добавлять без изменения существующего кода. Такой подход позволяет минимизировать риск возникновения ошибок в уже работающей системе при внедрении новых функций. **Принцип открытости/закрытости (Open-Closed Principle, OCP)** является вторым из пяти [[SOLID]]-принципов и способствует созданию гибкой и поддерживаемой архитектуры.
Обычно для реализации принципа используются:
- **Интерфейсы** или **абстрактные классы**, которые задают общую структуру поведения.
- [[Полиморфизм]], позволяющий создавать новые реализации без изменения базового кода.
Следование 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, так как для добавления нового функционала приходится изменять уже существующий код. Это увеличивает риск ошибок и затрудняет сопровождение.
Используем интерфейсы для реализации разных способов оплаты:
```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`, не изменяя код процессора.
***
## Мета информация
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
**Родитель**:: [[SOLID|SOLID]]
**Источник**::
**Создана**:: [[2024-09-27]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->