Агрегация vs Композиция
Вместо введения
Решил набросать небольшой пост по ООП... Вот пример композиции и агрегирования с точки зрения кода, написанного на Swift (на Python можно сделать по аналогии). Посмотрев на этот код, вы сможете оценить разницу между ними.
Кстати, в объектно-ориентированном дизайне композиция предпочтительнее наследования, о чем я говорил и в прошлой статье, и даже джавист Джошуа Блох заявлял о её важности в классической книге по Java (Effective Java).
Начать стоит вообще с того, что и агрегация и композиция – это подклассы ассоциации, ну или если можно так выразиться «частные случаи» её проявления. Ассоциация по сути говорит о взаимоотношении с объектом.
Когда мы говорим об ООП, мы всегда думаем об объектах (экземплярах класса), классе (своеобразном «blueprint'е» объектов) и отношениях между ними. Объекты связаны и взаимодействуют друг с другом с помощью методов. Если объект одного класса может использовать методы, предоставляемые объектом другого класса, то такие отношения называются ассоциациями.
Ну ладно, довольно болтологии. Как говорил Линус Торвальдс,
Talk is cheap. Show me the code.
Агрегация
Агрегация, или её ещё называют «слабая ассоциация» – это такой тип отношений, когда у класса есть объект, который он позаимствовал где-то еще (например у другого класса).
Вот например как на картинке выше. Если инстанс (объект) класса Library
будет уничтожен, books
будет продолжать своё существование, и наоборот.
Если не нравится пример с книгами, вот тут мой любимый пример с машинками и двигателями. Здесь важно понимать главное, «слабая ассоциация» подразумевает, что Car
не владеет Engine
. Engine
создается где-то вовне, и передается внутрь Car
. Это и есть агрегация.
Композиция
Композиция, или «сильная ассоциация» – это такой тип отношений, когда класс именно «владеет» объектом и несёт ответственность за его время жизни.
Теперь же если инстанс (объект) класса Reader
будет уничтожен (деинициализирован), вместе с ним умрёт и books
. Как вы уже могли заметить, в этом примере ничего не передается внутрь Reader
. Все объекты класса Book
создаются внутри самого Reader
.
А вот и пример с машинками. Поэтому композиция еще называется «сильной» ассоциацией, в этом случае Car
именно «владеет» Engine
и ответственен за время жизни его инстанса, если уничтожить инстанс класса Car
, пропадет и созданный внутри него инстанс Engine
.
Заключение
Грамотный выбор типа отношений между классами и объектами – залог успеха любого ООПшника! Давайте еще раз кратко подытожим все вышесказанное.
- Агрегация подразумевает такой тип отношений, в которых дочерняя структура может существовать независимо от родительской. Пример:
Person
(родительский класс) иStudent
(дочерний класс). ЕслиPerson
будет удалён,Student
всё равно продолжит существовать. - Композиция подразумевает такой тип отношений, в которых дочерняя структура не может существовать отдельно от родительской. Пример:
House
(родительский класс) иRoom
(дочерний класс).Room
не существует отдельно отHouse
.
Если логика задана так, что дочерней структуре необходимо существовать вне зависимости от родительской, значит нужно использовать агрегацию. Если нет – композицию.
Статья подготовлена для канала Hello World.