Агрегация против состава

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

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

12 ответов

Решение

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

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

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

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

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

Как правило большого пальца:

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

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

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

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

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

Состав и агрегация являются типами ассоциаций. Они очень тесно связаны между собой, и с точки зрения программирования нет большой разницы. Я попытаюсь объяснить разницу между этими двумя примерами кода 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”);
  }
}

Здесь поясняется пример Разница между агрегацией и составом

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

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

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

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

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

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

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

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

Но в то же время они также говорят

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

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

1) Композиция

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

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

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

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

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

2) Агрегация

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

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

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

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

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

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, обычно есть фабрика или два, чтобы пройти сначала!

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

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

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

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

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

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

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

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

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

Но, как отмечают другие, много раз, является ли соединение составом или объединением, зависит от приложения.

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

Далее из стандарта UML:

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

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

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

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

Другие вопросы по тегам