Обозначения диаграмм классов UML: различия между ассоциацией, агрегацией и композицией

39

Я запутался в некоторых обозначениях диаграмм классов UML.

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

Я уверен, что знаю, что такое Ассоциация . Любые отношения между экземплярами двух классов, где экземпляру одного класса необходимо знать об экземпляре второго класса для выполнения своей работы, - это отношения Ассоциации. Ассоциация часто означает, что класс A имеет ссылку (поле) на экземпляр класса B.

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

Два определения обозначения агрегации :

Определение 1: нотация агрегации между двумя классами подходит всякий раз, когда экземпляр класса A содержит коллекцию экземпляров класса B (например, List, Array и т. Д.).

Определение 2. Ссылка агрегации между двумя классами подходит, если экземпляр класса A содержит ссылку на экземпляр класса B, а экземпляр B зависит от жизненного цикла экземпляра A. Значение: когда экземпляр класса A удаляется, то же самое происходит и с экземпляром класса B. Экземпляр класса B полностью содержится в экземпляре класса A, в отличие от экземпляра класса A, просто владеющего ссылкой на экземпляр класса класс B (который является регулярной ассоциацией).

Что касается обозначения «Состав» и того, как оно отличается от обозначения «Агрегация», я не уверен.

Пожалуйста, уточните определения и помогите мне понять. Конкретные примеры приветствуются.

Авив Кон
источник
Определение 2 больше похоже на определение композиции, чем агрегации. Определение 1 звучит совершенно правильно.
jbx

Ответы:

32

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

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

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

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

Барт ван Инген Шенау
источник
1
Спасибо за Ваш ответ. Вот как я понимаю вещи, пожалуйста, скажите, если это разумное определение. 1- Ассоциация - это всякий раз, когда объект A должен знать об объекте B для выполнения его функциональных возможностей. 2. И Агрегация, и Композиция определяют отношение «владение» - экземпляру класса A концептуально принадлежит экземпляр класса B. Но время жизни экземпляра B не зависит от времени жизни экземпляра A. Например, отдел с сотрудниками. Департамент «владеет» экземпляром сотрудника, но он будет жить без отдела. Композиция как Агрегация, но
Авив Кон
1
время жизни экземпляра B зависит от времени жизни экземпляра A. Более сильные отношения собственности. Например: автомобиль и колесо. Автомобиль "полностью содержит" колесо. Экземпляр «Колесо» не будет жить без экземпляра «Автомобиль», содержащего его. Это разумная дифференциация?
Авив Кон
@Prog: Да, это разумное определение. Просто помните, что другие могут не согласиться с этим определением, и вам может потребоваться объяснить им использование агрегации.
Барт ван Инген Шенау
Что бы вы назвали наиболее распространенным определением для обозначения агрегации? Определение я использую? Определение «имеет коллекцию»? Что-то другое?
Авив Кон
Ссылка на стандарт OMG ниже поучительна. Ассоциация и состав довольно просты. Агрегация является шаткой. На практике я считаю, что «часть» теста работает хорошо («владение» - это неоптимальный способ думать об этом). Человек может быть частью клуба, таким образом, клуб объединяет людей (он не владеет ими). Когда клуб разрушен, люди продолжают существовать.
Huliax
10

Композиция - это когда object Aсодержит object Bи object Aтакже несет ответственность за создание object B.

Композиционные отношения

У нас есть класс A, который будет использоваться классом B.

final class A
{
}

Есть несколько вариантов того, как может выглядеть композиция.

Прямая инициализация композиции:

final class B
{
    private $a = new A();
}

Состав инициализации конструктора

final class B
{
    private $a;

    public function __construct()
    {
        $this->a = new A();
    }
}

Ленивая инициализация композиции

final class B
{
    private $a = null;

    public function useA()
    {
        if ($this->a === null) {
            $this->a = new A();
        }

        /* Use $this->a */
    }
}

Вы видите, что это создает тесные отношения между классами Aи B. Класс Bпросто не может существовать без A. Это огромное нарушение принципа внедрения зависимостей , которое гласит:

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

Композиция иногда имеет смысл, например, вызов new DateTime в php или new std::vector<int>в C ++. Но чаще всего это предупреждение о том, что ваш код написан неправильно.

В случае, когда class A будет специальным объектом, используемым для кэширования, class Bон всегда будет кэшироваться с использованием реализации class A, и у вас не будет контроля для его динамического изменения, что плохо.

Кроме того, если вы использовали ленивую композицию инициализации , то есть у вас есть рабочий object B, называемый useA()методом и созданиемobject A не удастся, ваш файл object Bвнезапно окажется бесполезным.


Агрегация, с другой стороны, является способом взаимоотношений, который следует принципу DI . object Bнеобходимо использовать object A, то вы должны передать уже созданный экземпляр object Aдляobject B , и если создание object Aзавершится ошибкой, ничего не будет передано в первую очередь.

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

Это все агрегации

Самая тесная инъекция в конструктор ( object Bне может существовать без object A).

final class B
{
    private $a;

    public function __construct(A $a)
    {
        $this->a = $a;
    }
}

Слабее (вы можете или не можете использовать object Aвнутри object B, но если вы это сделаете, вы, вероятно, должны установить его первым).

Через сеттер:

final class B
{
    private $a;

    public function setA(A $a)
    {
        $this->a = $a;
    }
}

Через общественную собственность:

final class B
{
    public $a;
}

На самом деле нет хорошего способа оправдать использование Aggregation over Composition, если все, что вы используете, - это конкретные реализации классов, но как только вы начнете внедрять интерфейсы или в случае абстрактных классов C ++, внезапно Aggregation станет единственным способом выполнить ваш контракт.

Энди
источник
1
Просмотр примеров кода действительно помогает! Пояснения на английском без кода кажутся такими расплывчатыми и субъективными.
Нико Беллик
1

Кроме того, выдержка из текущего стандарта UML:

11.5.4 Ассоциации - Семантика - Обозначения

[...] Двоичная ассоциация может иметь один конец с агрегатом = AggregationKind :: shared или агрегацией = AggregationKind :: Composite. Когда один конец имеет агрегации = AggregationKind :: общий полый алмаз добавляется в качестве терминала украшения в конце линии ассоциации противоположного конца , помеченной агрегации = AggregationKind :: совместно. Алмаз должен быть заметно меньше, чем обозначение алмаза для Ассоциаций. Ассоциация с агрегацией = AggregationKind :: Composite также имеет ромб на соответствующем конце, но отличается тем, что алмаз заполнен . […]

9.5.4 Классификация - Свойства - Обозначения

[…] Иногда свойство используется для моделирования обстоятельств, в которых один экземпляр используется для группировки набора экземпляров; это называется агрегацией. Для представления таких обстоятельств у свойства есть свойство агрегации типа AggregationKind; экземпляр, представляющий всю группу, классифицируется владельцем Имущества, а экземпляры, представляющие сгруппированных лиц, классифицируются по типу Имущества. AggregationKind - это перечисление со следующими литеральными значениями:

  • none : указывает, что свойство не имеет семантики агрегации.
  • Shared : указывает, что свойство имеет общую семантику агрегации. Точная семантика совместной агрегации зависит от области применения и модели.
  • Составной : указывает на то, что свойство агрегируется композитно, т. Е. Составной объект несет ответственность за существование и хранение составных объектов (см. Определение частей в 11.2.3). Составная агрегация - это сильная форма агрегации, которая требует, чтобы объект части включался не более чем в один составной объект одновременно. Если составной объект удаляется, все его экземпляры части, которые являются объектами, удаляются вместе с ним.

[...]

ManuelSchneid3r
источник
0

Я уже разместил ответ на Stackoverflow .

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

Композиция даже сильнее, чем агрегация, потому что агрегированный класс не может быть агрегирован другими классами. Его «жизнь» зависит от контейнера.

C.Champagne
источник