Связи между объектами
Термины описывают владение и жизненный цикл. Java не проверяет их отдельными ключевыми словами: смысл задаёт модель и код.
| Связь | Смысл | Жизненный цикл |
|---|---|---|
| ассоциация | один объект знает другой | независимый |
| агрегация | слабое «целое — часть» | часть живёт отдельно |
| композиция | сильное владение | часть создаётся/контролируется владельцем |
| наследование | отношение is-a | типовой контракт |
Ассоциация
record CustomerId(long value) {}
final class Invoice {
private final CustomerId customerId; // знает клиента по идентификатору
Invoice(CustomerId customerId) {
this.customerId = customerId;
}
}Направление бывает односторонним или двусторонним. Двусторонняя связь требует синхронно обновлять обе стороны и часто усложняет ORM-модель.
Агрегация
final class Team {
private final List<Employee> members;
Team(List<Employee> members) {
this.members = List.copyOf(members);
}
}Employee существует до и после Team и может участвовать в другой модели. Команда не отвечает за создание сотрудника.
Композиция
final class Order {
private final List<Line> lines = new ArrayList<>();
void add(Product product, int quantity) {
lines.add(new Line(product.id(), quantity));
}
private record Line(ProductId productId, int quantity) {}
}Line — внутренняя часть заказа, без него не имеет самостоятельной идентичности. Владелец защищает инварианты и не отдаёт изменяемую коллекцию наружу.
Композиция против наследования
Наследование уместно, когда подтип соблюдает контракт базового типа. Для повторного использования реализации чаще безопаснее композиция: зависимость можно заменить, а наружу не раскрывается весь API родителя.
Ошибки
- считать любое поле композицией;
- моделировать
is-aтолько ради повторного использования кода; - создавать двусторонние коллекции без методов, поддерживающих обе стороны;
- путать
cascade/orphanRemovalORM с полным смыслом доменного владения.
На собеседовании
Есть ли в Java оператор агрегации? Нет, это модельное отношение.
Чем композиция сильнее агрегации? Владелец контролирует идентичность и жизненный цикл части.
Почему часто выбирают композицию вместо наследования? Меньше связанность и уже публичный контракт.
Связано: Наследование, Инкапсуляция, Классы Java.