Ответ
Принцип открытости/закрытости (OCP): Программные сущности (классы, модули) должны быть открыты для расширения (новой функциональности) но закрыты для модификации (изменения существующего кода).
Пример нарушения: Класс ReportGenerator, который изменяется каждый раз при добавлении нового формата отчета.
// НАРУШЕНИЕ OCP: Класс приходится МОДИФИЦИРОВАТЬ для добавления поддержки нового типа.
class ReportGenerator {
public String generateReport(String type, Data data) {
if (type.equals("PDF")) {
// Логика генерации PDF
return generatePdf(data);
} else if (type.equals("HTML")) {
// Логика генерации HTML
return generateHtml(data);
} else if (type.equals("CSV")) {
// Логика генерации CSV (добавлена позже)
return generateCsv(data);
}
throw new IllegalArgumentException("Unsupported report type: " + type);
}
private String generatePdf(Data d) { /* ... */ }
private String generateHtml(Data d) { /* ... */ }
private String generateCsv(Data d) { /* ... */ } // Пришлось добавить новый метод
}
Проблемы такого подхода:
- Риск регрессии: Изменение кода для добавления CSV может случайно сломать генерацию PDF или HTML.
- Нарушение SRP: Класс берет на себя ответственность за знание о всех возможных форматах.
- Сложность тестирования: Монолитный метод, который нужно тестировать на все большее число сценариев.
Решение, соответствующее OCP:
// 1. Абстракция, закрытая для модификации.
interface ReportGenerator {
String generate(Data data);
}
// 2. Конкретные реализации, открытые для расширения.
class PdfReportGenerator implements ReportGenerator {
@Override
public String generate(Data data) { /* ... */ }
}
class HtmlReportGenerator implements ReportGenerator {
@Override
public String generate(Data data) { /* ... */ }
}
// 3. Новый формат добавляется БЕЗ изменения существующего кода.
class CsvReportGenerator implements ReportGenerator {
@Override
public String generate(Data data) { /* ... */ }
}
// 4. Клиентский код использует абстракцию.
class ReportService {
private final ReportGenerator generator;
public ReportService(ReportGenerator generator) { this.generator = generator; }
public void createReport(Data data) {
String report = generator.generate(data); // Закрыто для модификации
// ...
}
}
Теперь для добавления формата XML нужно лишь создать новый класс XmlReportGenerator, не трогая ReportService, PdfReportGenerator или другие существующие генераторы.