digital-garden/dev/architecture/Liskov Substitution 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

82 lines
4.7 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:
- LSP
- Принцип подстановки Барбары Лисков
tags:
- maturity/🌱
date: 2024-09-27
---
Принцип подстановки Лисков (Liskov Substitution Principle, LSP) утверждает, что ==объекты подклассов должны быть взаимозаменяемы с объектами базового класса без изменения поведения программы==. Это означает, что ==подклассы не должны нарушать контракт базового класса или изменять его логику==. LSP является третьим принципом в набор[[SOLID|е SOL]]ID и играет ключевую роль в создании устойчивой и понятной иерархии классов.
**Чтобы соответствовать LSP:**
- Подклассы должны расширять функциональность базового класса, не изменяя его поведение.
- [[Контракт взаимодействия|Контракты]], задаваемые базовыми классами, должны строго соблюдаться.
- Следует избегать переопределения методов, если это изменяет их ожидаемое поведение.
**Преимущества соблюдения LSP:**
1. **Предсказуемость:** Код, использующий базовый класс, будет работать одинаково независимо от того, какие подклассы используются.
2. **Упрощение тестирования:** Система становится менее подверженной ошибкам, так как базовый контракт всегда соблюдается.
3. **Гибкость и масштабируемость:** Добавление новых подклассов не требует модификации существующего кода, если соблюден принцип LSP.
4. **Улучшенная читаемость:** Четкое разделение обязанностей между базовыми и дочерними классами упрощает понимание системы.
## Пример нарушения LSP
Рассмотрим иерархию классов для птиц:
```java
public class Bird {
public void fly() {
// Логика полета
System.out.println("I can fly!");
}
}
public class Penguin extends Bird {
@Override
public void fly() {
// Пингвин не может летать — нарушение LSP
throw new UnsupportedOperationException("Penguins cannot fly");
}
}
```
В данном случае класс `Penguin` нарушает контракт базового класса `Bird`. Код, который ожидает, что любой объект типа `Bird` может летать, перестанет работать корректно при использовании `Penguin`. Это ведет к непредсказуемому поведению программы и увеличивает сложность сопровождения.
Для устранения нарушения следует пересмотреть иерархию классов, чтобы явно выделить летающих и нелетающих птиц:
```java
public abstract class Bird {
// Общие свойства и методы для всех птиц
}
public interface Flyable {
void fly();
}
public class FlyingBird extends Bird implements Flyable {
@Override
public void fly() {
// Реализация полета
System.out.println("I can fly!");
}
}
public class Penguin extends Bird {
// Пингвин остается нелетающей птицей
}
```
Теперь поведение каждой птицы становится очевидным, и программа корректно работает с летающими и нелетающими птицами, не нарушая LSP.
***
## Мета информация
**Область**:: [[../../meta/zero/00 Архитектура ПО|00 Архитектура ПО]]
**Родитель**:: [[SOLID]]
**Источник**::
**Создана**:: [[2024-09-27]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->