Ответ
Преимущества композиции ("has-a" отношение):
- Гибкость и слабая связанность: Позволяет динамически изменять поведение объекта во время выполнения, подменяя компоненты. Классы менее зависимы друг от друга.
- Инкапсуляция: Внутренняя структура и реализация компонентов полностью скрыты от содержащего их объекта. Доступ происходит через четко определенный интерфейс.
- Избегание проблем наследования: Решает проблему хрупкого базового класса (fragile base class) и исключает ограничения, связанные с отсутствием множественного наследования в языках вроде Java.
- Упрощение тестирования: Компоненты можно тестировать изолированно, а в содержащем классе — использовать моки или заглушки.
Недостатки / Сложности композиции:
- Большее количество классов: Проект может содержать множество мелких классов, что увеличивает сложность навигации.
- Делегирование вызовов: Требуется явно реализовывать методы, которые просто делегируют вызовы внутренним объектам, что может привести к шаблонному коду.
- Инициализация и управление жизненным циклом: Создание и настройка составного объекта может быть сложнее, чем создание объекта через наследование.
Пример на Java:
// Компоненты
class Engine {
public void start() { System.out.println("Двигатель запущен"); }
}
class Transmission {
public void shiftGear(int gear) { System.out.println("Включена передача: " + gear); }
}
// Класс, использующий композицию
class Car {
// Композиция: Car HAS-A Engine и HAS-A Transmission
private final Engine engine;
private final Transmission transmission;
public Car(Engine engine, Transmission transmission) {
this.engine = engine;
this.transmission = transmission;
}
// Делегирование ответственности компонентам
public void startCar() {
engine.start();
transmission.shiftGear(1);
}
// Легко заменить компонент, например, на TurboEngine
public void setEngine(Engine newEngine) {
this.engine = newEngine;
}
}