Агрегация против композиции [закрыто]


91

Мне было трудно понять разницу между композицией и агрегированием в UML. Может кто-нибудь предложить мне хорошее сравнение и контраст между ними? Я также хотел бы научиться распознавать разницу между ними в коде и / или увидеть короткий пример программного обеспечения / кода.

Изменить: отчасти причина, по которой я спрашиваю, связана с обратной документацией, которую мы делаем на работе. Мы написали код, но нам нужно вернуться и создать диаграммы классов для кода. Мы просто хотим правильно передать ассоциации.



Пожалуйста, проверьте пример кода по адресу: stackoverflow.com/questions/731802/…
Альмир Кампос

UML 2.5 прояснил разницу. Смотрите рамку на стр. 110. Итак, я голосую за то, чтобы снова открыть это.
qwerty_so

Нет, UML 2.5 не разъясняет определение композиции, скорее, он остается неоднозначным по этому поводу, поскольку они также говорят: «Частичный объект может быть удален из составного объекта до того, как будет удален составной объект, и, следовательно, не может быть удален как часть составной объект ". См. Мой ответ ниже ( stackoverflow.com/questions/734891/… ), где я попытался прояснить смысл композиции. Пожалуйста, проголосуйте за мой ответ, чтобы показать, что в SO правильный ответ в конце концов побеждает :-) [или проголосуйте против всех неправильных ответов]
Герд Вагнер

Ответы:


91

Различие между агрегацией и составом зависит от контекста.

Возьмем пример автомобиля, упомянутый в другом ответе - да, это правда, что выхлоп автомобиля может работать «сам по себе», поэтому он может не входить в состав автомобиля, но это зависит от приложения. Если вы создаете приложение, которое действительно имеет дело с автономными автомобильными выхлопами (приложение для управления автосервисом?), То вам будет лучше агрегировать. Но если это простая гоночная игра, и выхлоп машины служит только частью машины - что ж, композиция будет вполне подходящей.

Шахматная доска? Та же проблема. Шахматная фигура без шахматной доски не существует только в определенных приложениях. В других случаях (например, у производителя игрушек) из шахматной фигуры определенно нельзя составить шахматную доску.

Ситуация становится еще хуже, когда вы пытаетесь сопоставить композицию / агрегирование с вашим любимым языком программирования. В некоторых языках разницу легче заметить («по ссылке» или «по значению», когда все просто), но в других может вообще не существовать.

И последний совет? Не тратьте слишком много времени на этот вопрос. Это того не стоит. Это различие вряд ли полезно на практике (даже если у вас есть полностью четкая «композиция», вы все равно можете захотеть реализовать ее как агрегирование по техническим причинам - например, из-за кеширования).


1
Я сказал «шахматный квадрат», а не «шахматную фигуру», но все правильные.
Дэвид М.

2
Я определенно не согласен с мышлением «Это того не стоит». Если вы не продумаете, кто «владеет» объектом и несет ответственность за его продолжительность жизни, вы получите очень дрянной код, связанный с CRUD объекта, особенно с очисткой, с летающими указателями Null, поскольку иерархии объектов остаются в плохом состоянии.
Крис Кессель,

9
Да, не стоит тратить слишком много времени на этот вопрос: UML - это язык OOA / OOD; Агрегация / композиция обычно - это решение, которое лучше отложить до ООП. Если вы попытаетесь вложить слишком много деталей в свои модели UML, вы рискуете параличом анализа.
chimp

14
+1 за «не тратьте на это слишком много времени». Вот что мне нужно было услышать!
Ронни

9
«не тратьте на это слишком много времени» Почему интервьюеры этого не понимают?
titogeo

98

Как правило большого пальца: введите описание изображения здесь

class Person {
    private Heart heart;
    private List<Hand> hands;
}

class City {
    private List<Tree> trees;
    private List<Car> cars
}

В композиции (Человек, Сердце, Рука) «подобъекты» (Сердце, Рука) будут уничтожены, как только будет уничтожен Человек.

В совокупности (Город, Дерево, Автомобиль) «подобъекты» (Дерево, Автомобиль) НЕ будут уничтожены при разрушении Города.

Суть в том, что композиция делает упор на взаимное существование, и в совокупности это свойство НЕ требуется.


2
взаимное существование, добрый B-)
jxramos

Оцените ваши усилия. Очень хорошее объяснение, и это может понять любой непрофессионал.
Равиндран Канния,

Самое простое и лучшее объяснение, с которым я столкнулся.
Акаш

лучшее объяснение :)
Xiabili

UML 2.5 прояснил разницу. Смотрите рамку на стр. 110. Итак, ваш ответ сейчас просто неверен,
qwerty_so

56

Состав и агрегирование - это типы ассоциаций. Они очень тесно связаны, и с точки зрения программирования, похоже, между ними нет большой разницы. Я постараюсь объяснить разницу между этими двумя примерами java-кода.

Агрегация : объект существует вне другого, создается снаружи, поэтому он передается в качестве аргумента (например) конструктору. Пример: Люди - машина. Автомобиль создается в другом контексте и затем становится собственностью человека.

// code example for Aggregation:
// reference existing HttpListener and RequestProcessor
public class WebServer {
  private HttpListener listener;
  private RequestProcessor processor;
  public WebServer(HttpListener listener, RequestProcessor processor) {
    this.listener = listener;
    this.processor = processor;
  }
}

Композиция : объект существует или имеет смысл только внутри другого, как часть другого. Пример: Люди - сердце. Вы не создаете сердце, а затем передаете его человеку. Вместо этого, когда создается человек, создается сердце.

// code example for composition:
// create own HttpListener and RequestProcessor
public class WebServer {
  private HttpListener listener;
  private RequestProcessor processor;
  public WebServer() {
    this.listener = new HttpListener(80);
    this.processor = new RequestProcessor(“/www/root”);
  }
}

Объясняется здесь на примере Различия между агрегированием и композицией


6
Один из лучших ответов на данный момент. Аккуратно :)
Рохит Сингх

6
Лучший пример кода Java, показывающий, когда объект может существовать с (составом) или без (агрегирование) другими объектами.
Michał

пожалуйста, я хочу знать, следует ли использовать final для композиции или нет?
Outreagous ONE

−1. Разница между композицией и агрегированием не имеет ничего общего с тем, может ли часть существовать только внутри целого или нет (двигатель может существовать вне автомобиля, но их связь - это не агрегирование, а композиция). Это связано с тем, является ли часть уникальной или совместно используемой для разных целых, то есть от того, равна ли верхняя граница множественности целых, связанных с частью, 1 или нет, то есть от того, является ли отношение часть – целое функциональным (право- уникальный) или нет. См. Ответ Герда Вагнера.
Maggyero

36

Композиция подразумевает, что дочерние объекты разделяют продолжительность жизни с родительскими. Агрегация - нет. Например, шахматная доска состоит из шахматных квадратов - шахматных квадратов без доски на самом деле не существует. Однако автомобиль - это совокупность частей: выхлоп автомобиля остается выхлопом автомобиля, если он не является частью автомобиля в то время.


18

Пример, который я усвоил, - пальцы на руке. Ваша рука состоит из пальцев. Он им владеет. Если рука умирает, умирают пальцы. Вы не можете «объединить» пальцы. Вы не можете просто взять лишние пальцы, прикрепить и отсоединить их от руки по своему желанию.

Ценность здесь, с точки зрения дизайна, часто связана со сроком службы объекта, как сказал другой плакат. Допустим, у вас есть клиент и у него есть учетная запись. Эта Учетная запись является «составным» объектом клиента (по крайней мере, в большинстве контекстов, которые я могу придумать). Если вы удалите Клиента, Учетная запись не будет иметь самостоятельной ценности, поэтому она также будет удалена. При создании объекта часто бывает наоборот. Поскольку Учетная запись имеет значение только в контексте Клиента, у вас будет создание Учетной записи как часть создания Клиента (или, если вы делаете это лениво, это будет частью некоторой транзакции Клиента).

В дизайне полезно подумать о том, какие объекты владеют (составляют) другие объекты, а какие просто ссылаются (объединяют) другие объекты. Это может помочь определить, где лежит ответственность за создание / очистку / обновление объекта.

Что касается кода, то часто сложно сказать. Почти все в коде является ссылкой на объект, поэтому может быть неочевидно, состоит ли объект, на который ссылается, (принадлежит) или агрегирован.


16

Удивительно, как много путаницы существует в отношении различия между агрегированием и составом концепций ассоциации « часть – целое». . Основная проблема - это широко распространенное заблуждение (даже среди опытных разработчиков программного обеспечения и среди авторов UML), что концепция композиции подразумевает зависимость жизненного цикла между целым и его частями, так что части не могут существовать без целого. Но эта точка зрения игнорирует тот факт, что бывают также случаи ассоциаций части и целого с неделимыми частями, когда части могут быть отделены от целого и пережить разрушение целого.

В документе спецификации UML определение термина «композиция» всегда подразумевало не разделяемые части, но не было ясно, что является определяющей характеристикой «композиции», а что является просто необязательной характеристикой. Даже в новой версии (по состоянию на 2015 год), UML 2.5, после попытки улучшить определение термина «композиция», он остается неоднозначным и не дает никаких указаний по моделированию частично целых ассоциаций с не разделяемыми части, в которых части могут быть отделены от целого и выдерживают разрушение целого, в отличие от случая, когда части не могут быть отделены и разрушаются вместе с целым. Они говорят

При удалении составного объекта все экземпляры его частей, являющиеся объектами, удаляются вместе с ним.

Но в то же время говорят

Частичный объект может быть удален из составного объекта перед удалением составного объекта и, таким образом, не может быть удален как часть составного объекта.

Эта путаница указывает на неполноту определения UML, которое не учитывает зависимости жизненного цикла между компонентами и композитами. Поэтому важно понимать, как определение UML может быть улучшено путем введения стереотипа UML для « неотделимых» композиций, когда компоненты не могут быть отделены от их композиции и, таким образом, должны уничтожаться всякий раз, когда их композиция разрушается.

Сочинение

Как объяснил Мартин Фаулер , главная проблема для характеристики композиции состоит в том, что «объект может быть только частью одного отношения композиции». Это также объясняется в отличном сообщении блога « Состав UML против агрегирования против ассоциации » Гирта Беллекенса. В дополнение к этой определяющей характеристике композиции (иметь эксклюзивные или не подлежащие совместному использованию части) композиция также может иметь зависимость жизненного цикла между композитом и его компонентами. На самом деле существует два вида таких зависимостей:

  1. Каждый раз, когда компонент всегда должен быть присоединен к композиту, или, другими словами, когда он имеет обязательный состав , что выражается кратностью "ровно один" на композитной стороне линии компоновки, он должен либо использоваться повторно. в (или повторно присоединен) к другому составу, или уничтожается, когда его текущий состав разрушается. Примером этого служит композиция между Personи Heart, показанная на диаграмме ниже. Сердце либо разрушается, либо пересаживается другому человеку, когда его владелец умирает.
  2. Когда компонент не может быть отделен от своего композита, или, другими словами, когда он неразделим , тогда и только тогда компонент должен быть уничтожен, когда его состав разрушен. Примером такой композиции с неразрывными частями является композиция между Personи Brain.

Человек-мозг-сердце

Таким образом, зависимости жизненного цикла применимы только к конкретным случаям композиции, но не в целом, поэтому они не являются определяющей характеристикой.

Спецификация UML гласит: «Часть может быть удалена из составного экземпляра до того, как будет удален составной экземпляр, и, следовательно, не может быть удалена как часть составного экземпляра». В примере композиции Car- Engine, как показано на следующей диаграмме, очевидно, что двигатель может быть отсоединен от автомобиля до того, как автомобиль будет разрушен, и в этом случае двигатель не будет разрушен и может быть использован повторно. Это подразумевается нулевой или одной кратностью на составной стороне линии композиции.

введите описание изображения здесь

Кратность конца ассоциации композиции , по меньшей композиционной стороне равна 1 или 0..1, в зависимости от того , если компоненты имеют обязательный композит (должно быть присоединены к составному) или нет. Если компоненты неразделимы , это означает, что они имеют обязательную композицию.

Агрегация

Агрегация - это еще одна особая форма ассоциации с предполагаемым значением отношения «часть – целое», когда части целого могут быть разделены с другими целыми. Например, мы можем смоделировать агрегацию между классами DegreeProgramи Course, как показано на следующей диаграмме, поскольку курс является частью программы на получение степени, и курс может быть разделен между двумя или более программами получения степени (например, степень инженера может совместно использовать C курс программирования со степенью информатики).

введите описание изображения здесь

Однако концепция агрегации с разделяемыми частями на самом деле не имеет большого значения, поэтому она не имеет никаких последствий для реализации, и поэтому многие разработчики предпочитают не использовать белый ромб в своих диаграммах классов, а просто моделировать простую ассоциацию. вместо. Спецификация UML гласит: «Точная семантика совместной агрегации зависит от области приложения и разработчика».

Кратность конца ассоциации агрегации по крайней всей стороне может быть любое число (*) , так как часть может принадлежать или совместно среди, любого количества целостностей.


2
Композиция строго не связана с жизненным циклом, но в большинстве реальных проблем жизненный цикл является основным мотиватором того, будете ли вы составлять или объединять. Я сдержался в своем ответе, сказав, что жизненный цикл «часто» связан, а не всегда связан. Приятно отметить, что жизненный цикл не требуется, но указание на то, что представление является «основной проблемой» и неправильным (красивым полужирным шрифтом), кажется мне бесполезным и отвлекает от указания на практические аспекты использования.
Крис Кессель

1
Я категорически не согласен. Соображения жизненного цикла не могут быть «первичным мотиватором того, собираетесь ли вы составлять или объединять», поскольку они есть во многих случаях ассоциаций независимо от того, представляют ли они какой-либо вид взаимодействия части-целого (агрегация или композиция). Всякий раз, когда ассоциация имеет конец с кратностью нижней границы больше 0, соответствующей обязательному ссылочному свойству, вы получите зависимость жизненного цикла.
Герд Вагнер,

1
@Maggyero: только если часть является обязательной, требуется минимальная мощность 1. В случае человеческого сердца это, безусловно, так, и я исправил диаграмму выше. Но в случае с двигателем автомобиля можно сказать, что автомобиль по-прежнему остается автомобилем, даже без двигателя. В случае программы на получение степени, если диаграмма представляет модель предметной области, тогда действительно должен быть хотя бы один назначенный курс. Но если я представляю модель дизайна класса, мы можем предпочесть не требовать назначенного курса.
Герд Вагнер

1
@Maggyero: Интересный вопрос. Характеристика конца ассоциации мозга {только для чтения} будет означать, что назначение мозга не может быть изменено, но будет ли это также означать, что при разрушении человека мозг не может быть отделен, но также должен быть разрушен? Я так не думаю.
Герд Вагнер

1
Да, я предлагаю определить «нераздельный» стереотип сложных ассоциаций и использовать его в этих случаях.
Герд Вагнер

8

В терминах кода композиция обычно предполагает, что содержащий объект отвечает за создание экземпляров компонента *, а содержащий объект содержит только долгоживущие ссылки на него. Таким образом, если ссылка на родительский объект прекращается и происходит сборка мусора, то же самое произойдет и с дочерним объектом.

так что этот код ...

Class Order
   private Collection<LineItem> items;
   ...
   void addOrderLine(Item sku, int quantity){
         items.add(new LineItem(sku, quantity));
   }
}

предполагает, что LineItem является компонентом Order - LineItems не существуют вне порядка, в котором они содержатся. Но объекты Item не создаются в порядке - они передаются по мере необходимости и продолжают существовать, даже если в магазине нет заказов. поэтому они связаны, а не компоненты.

* nb контейнер отвечает за создание экземпляра компонента, но он может не вызывать сам new ... () - это java, обычно сначала нужно пройти через фабрику или две!


0

Концептуальные иллюстрации, представленные в других ответах, полезны, но я хотел бы поделиться еще одним важным моментом.

Я получил некоторый опыт использования UML для генерации кода, для исходного кода или DDL для реляционной базы данных. Здесь я использовал композицию, чтобы указать, что таблица имеет внешний ключ, не допускающий значения NULL (в базе данных), и не допускающий значения NULL «родительский» (и часто «конечный») объект в моем коде. Я использую агрегацию, когда я хочу, чтобы запись или объект могли существовать как «сирота», не прикрепляться ни к какому родительскому объекту или быть «усыновленными» другим родительским объектом.

Другими словами, я использовал обозначение композиции как сокращение, чтобы обозначить некоторые дополнительные ограничения, которые могут потребоваться при написании кода для модели.


0

Пример, который мне нравится: Состав: Вода - часть пруда. (Пруд представляет собой состав воды.) Агрегация: Пруд имеет утки и рыбы (в пруду - утки и рыба).

Как вы можете видеть, я выделил жирным шрифтом «часть из» и «имеет», поскольку эти две фразы обычно указывают на то, какая связь существует между классами.

Но, как указывали другие, во многих случаях, является ли соединение композицией или агрегацией, зависит от приложения.


Но иногда смущает часть и термины. Например, класс Person "имеет" имя, поэтому отображается, как Person имеет отношение агрегирования с именем. Фактически, это композиционное отношение. Почему? Когда объект Person разрушается, имя должно быть таким же. И термин «имя - часть лица» звучит неестественно.
Асиф Шахзад

0

Так сложно провести различие между совокупным отношением и составным отношением, но я собираюсь привести несколько примеров: у нас есть дом и комнаты, здесь у нас есть составное отношение, комната - это часть дома, и жизнь в комнате началась. с домашней жизнью и завершится, когда жизнь в доме закончится, комната - это часть дома, мы говорим о композиции, например, о стране и столице, книге и страницах. В качестве примера совокупного отношения возьмите команду и игроков, игрок может существовать без команды, а команда - это группа игроков, и жизнь игрока может начаться раньше жизни команды, если мы говорим о программировании, мы можем создавать игроков и после того, как мы создадим команду, но для композиции №, мы создаем комнаты внутри дома. Композиция ----> композит | составление. Агрегация -------> группа | элемент


0

Установим сроки. Агрегация - это метатерм в стандарте UML, который означает ОБА композицию и общую агрегацию, называемую просто shared . Часто это неправильно называют «агрегацией». Это ПЛОХО, потому что композиция - это тоже агрегирование. Насколько я понимаю, вы имеете в виду «общий».

Дополнительно от стандарта UML:

составной - указывает, что свойство агрегировано составно, т. е. составной объект несет ответственность за существование и хранение составных объектов (частей).

Итак, ассоциация университета и кафедры - это композиция, потому что кафедра не существует вне университета (ИМХО).

Точная семантика совместной агрегации зависит от области приложения и разработчика.

Т.е. все остальные ассоциации могут быть нарисованы как общие агрегаты, если вы следуете только каким-то своим или чужим принципам. Также смотрите здесь .


0

Рассмотрим такие части человеческого тела, как почки, печень, мозг. Если мы попытаемся отобразить здесь концепцию композиции и агрегации, это будет примерно так:

До появления трансплантации частей тела, таких как почки и печень, эти две части тела входили в состав человеческого тела и не могли существовать изолированно от человеческого тела.

Но после появления трансплантации частей тела их можно пересаживать в другое человеческое тело, поэтому эти части находятся в совокупности с человеческим телом, поскольку теперь их существование изолированно от человеческого тела возможно.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.