Карта / SOLID / O, L, I, D

O, L, I, D

Четыре оставшихся принципа SOLID (первый, SRP, — в теме «S — единственная ответственность»):

O — Open/Closed. Класс должен быть открыт для расширения, закрыт для изменения — добавляешь новое поведение через новый код, не трогая старый:

// вместо if-else по типу — новый класс на каждый случай (паттерн Strategy)
interface Discount { int apply(int price); }
class NewYearDiscount implements Discount { ... }   // добавил — старое не тронул

L — Liskov Substitution. Наследник должен полностью заменять родителя без сюрпризов — подробный разбор с примером “квадрат-прямоугольник” в теме «LSP, композиция vs наследование».

I — Interface Segregation. Лучше много маленьких интерфейсов, чем один большой “интерфейс на всё”:

// ❌ плохо: реализующий класс вынужден писать пустые методы
interface Worker { void work(); void eat(); void sleep(); }

// ✅ хорошо: реализуешь только то, что реально нужно
interface Workable { void work(); }
interface Eatable { void eat(); }
class Robot implements Workable { void work() { ... } }   // роботу не нужен eat()

D — Dependency Inversion. Зависеть от абстракций (интерфейсов), а не от конкретных реализаций:

// ❌ плохо: жёстко привязан к конкретному классу
class OrderService {
    private MySqlRepository repo = new MySqlRepository();
}

// ✅ хорошо: зависит от интерфейса, реализацию можно подменить
class OrderService {
    private final OrderRepository repo;   // интерфейс
    OrderService(OrderRepository repo) { this.repo = repo; }   // подставляется снаружи
}
Копнуть глубже

Open/Closed на практике почти всегда реализуется через полиморфизм/паттерны (Strategy, Decorator) — вместо того чтобы лезть в существующий метод и дописывать туда ещё один else if, создаёшь новый класс, реализующий тот же интерфейс.

Interface Segregation предотвращает “толстые” интерфейсы, которые заставляют классы реализовывать ненужные им методы пустышками — это явный признак, что интерфейс делает слишком много и его пора разделить.

Dependency Inversion — основа всего Spring. Когда внедряешь зависимость через конструктор (@Autowired или просто конструктор с интерфейсом параметром), ты явно следуешь этому принципу: OrderService не создаёт OrderRepository сам, а получает его готовым снаружи — это и называется инверсией управления (IoC), на которой держится весь Spring.

🎤 Закрыл тему, если можешь объяснить:
• своими словами кратко объяснить O, L, I, D на примерах;
• как Dependency Inversion связан с тем, как работает Spring (если дошёл до 2-го слоя).