В чем разница между объединением, агрегацией и составом? - PullRequest
344 голосов
/ 20 мая 2009

В чем разница между объединением, агрегацией и составом? Пожалуйста, объясните с точки зрения реализации.

Ответы [ 16 ]

326 голосов
/ 01 мая 2012

Для двух объектов, Foo и Bar могут быть определены отношения

Ассоциация - У меня отношения с объектом. Foo использует Bar

public class Foo { 
    void Baz(Bar bar) {
    } 
};

Композиция - Я владею объектом и отвечаю за его жизнь. Когда умирает Foo, Bar

public class Foo {
    private Bar bar = new Bar(); 
}

Агрегация - У меня есть предмет, который я позаимствовал у кого-то другого. Когда Foo умирает, Bar может жить.

public class Foo { 
    private Bar bar; 
    Foo(Bar bar) { 
       this.bar = bar; 
    }
}
101 голосов
/ 09 ноября 2014

Я знаю, что этот вопрос помечен как C #, но концепции довольно общие вопросы, такие как перенаправление здесь. Поэтому я собираюсь изложить свою точку зрения здесь (немного предвзято с точки зрения Java, где мне удобнее).

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

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

enter image description here

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

Confused?

Пример композиции : рассмотрим пример автомобиля и двигателя, который очень специфичен для этого автомобиля (то есть его нельзя использовать ни в каком другом автомобиле). Этот тип отношений между Car и SpecificEngine class называется Composition. Объект класса Car не может существовать без объекта класса SpecificEngine, а объект класса SpecificEngine не имеет значения без класса Car. Проще говоря, класс Car является единственным владельцем класса SpecificEngine.

Пример агрегации : Теперь рассмотрим класс Автомобиль и класс Колесо . Автомобиль нуждается в объекте Колесо, чтобы функционировать. То есть объект Car владеет объектом Wheel, но мы не можем сказать, что объект Wheel не имеет значения без объекта Car. Его очень хорошо можно использовать на велосипеде, грузовике или в другом объекте автомобилей.

Подводя итог -

Подводя итог, можно сказать, что ассоциация - это очень общий термин, используемый для обозначения того, когда класс использует функции, предоставляемые другим классом. Мы говорим, что это композиция, если один объект родительского класса владеет другим объектом дочернего класса, и этот объект дочернего класса не может существенным образом существовать без объекта родительского класса. Если это возможно, то это называется Агрегация.

Подробнее здесь. Я являюсь автором http://opensourceforgeeks.blogspot.in и добавил ссылку выше на соответствующий пост для получения дополнительной информации.

68 голосов
/ 24 июля 2015

Ассоциация является обобщенной концепцией отношений. Включает в себя как состав, так и агрегацию.

Композиция ( смесь ) - это способ объединения простых объектов или типов данных в единицу . Композиции являются важным строительным блоком многих базовых структур данных

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

Оба обозначают отношения между объектами и отличаются только их силой.

Трюк, чтобы запомнить разницу: имеет A - A скопление и O wn - c O mpositoin

enter image description here

Теперь рассмотрим следующее изображение

relations

enter image description here

Аналогия:

Композиция : Следующая картинка представляет собой композицию изображения, т.е. с использованием отдельных изображений, составляющих одно изображение.
enter image description here

Агрегация : коллекция изображений в одном месте

enter image description here

Например, В университете есть различные факультеты, и на каждом факультете есть несколько профессоров. Если университет закроется, кафедры больше не будут существовать, но профессора на этих кафедрах продолжат существовать. Следовательно, университет можно рассматривать как состав кафедр, тогда как кафедры имеют совокупность профессоров. Кроме того, профессор может работать на нескольких факультетах, но факультет не может быть частью более чем одного университета.

42 голосов
/ 03 декабря 2015

Зависимость (ссылки)
Это означает, что между двумя объектами нет концептуальной связи. например Ссылки на объект EnrollmentService. Объекты Student и Course (как параметры метода или возвращаемые типы)

public class EnrollmentService {
    public void enroll(Student s, Course c){}
}

Ассоциация (has-a)
Это означает, что почти всегда есть связь между объектами (они связаны). Объект заказа имеет Объект клиента

public class Order {
    private Customer customer
}

Агрегация (has-a + целая часть)
Особый вид ассоциации, когда между двумя объектами существует целостная связь. хотя они могут жить друг без друга.

public class PlayList{
    private List<Song> songs;
}

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

Композиция (has-a + целая часть + владение)
Особый вид агрегации. Apartment состоит из нескольких Room с. Room не может существовать без Apartment. при удалении квартиры удаляются также все связанные комнаты.

public class Apartment{
    private Room bedroom;
    public Apartment() {
       bedroom = new Room();
    }
}
28 голосов
/ 01 февраля 2010

Из поста Роберт Мартин в comp.object :

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

//[Example:]

//|A|----------->|B|

class A
{
  private:
    B* itsB;
};

Агрегация [...] является типичным отношением целое / часть. Это то же самое, что и ассоциация, за исключением того, что экземпляры не могут иметь отношения циклического агрегирования (то есть часть не может содержать свое целое).

//[Example:]

//|Node|<>-------->|Node|

class Node
{
  private:
    vector<Node*> itsNodes;
};

Тот факт, что это агрегация, означает, что экземпляры Node не могут образовывать цикл. Таким образом, это дерево узлов, а не граф узлов.

Композиция [...] точно такая же, как Агрегация, за исключением того, что время жизни «части» контролируется «целым». Этот контроль может быть прямым или переходным. То есть «целое» может взять на себя прямую ответственность за создание или уничтожение «части», или оно может принять уже созданную часть, а затем передать ее какому-то другому целому, которое берет на себя ответственность за нее.

//[Example:]

//|Car|<#>-------->|Carburetor|

class Car
{
  public:
    virtual ~Car() {delete itsCarb;}
  private:
    Carburetor* itsCarb
};
21 голосов
/ 20 мая 2009

Как говорили другие, ассоциация - это связь между объектами, агрегация и композиция - это типы ассоциации.

С точки зрения реализации агрегация получается при наличии члена класса по ссылке . Например, если класс A агрегирует объект класса B, у вас будет что-то вроде этого (в C ++):

class A {
    B & element;
  // or B * element;
};

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

class A {
    B element;
};

Здесь, когда объект A уничтожается, объект B, который он содержит, также будет уничтожен. Самый простой способ добиться этого - сохранить член по значению, но вы также можете использовать некоторый умный указатель или удалить член в деструкторе:

class A {
    std::auto_ptr<B> element;
};

class A {
    B * element;

    ~A() {
        delete B;
    }
};

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

12 голосов
/ 20 февраля 2017

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

Ассоциация

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

Слабая ассоциация

ClassA может быть связан с ClassB, чтобы показать, что один из его методов включает параметр экземпляра ClassB или возвращает экземпляр ClassB.

Сильная Ассоциация

ClassA также может быть связан с ClassB, чтобы показать, что он содержит ссылку на экземпляр ClassB.

Агрегация (общая ассоциация)

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

enter image description here

Важно отметить, что ссылка агрегации никоим образом не указывает, что ClassA владеет ClassB, или что между ними есть отношения родитель-потомок (когда родитель удалял все его дочерние элементы удаляются). На самом деле, совсем наоборот! Ссылка агрегации обычно используется, чтобы подчеркнуть тот факт, что ClassA не является эксклюзивным контейнером ClassB, поскольку на самом деле ClassB имеет другой контейнер.

Агрегация против. Ассоциация Ссылка на ассоциацию может заменить ссылку агрегации в любой ситуации, в то время как агрегация не может заменить ассоциацию в ситуациях, когда существует только «слабая связь» между классами, то есть ClassA имеет метод (ы), которые содержат параметр ClassB, но ClassA не содержит ссылку на Экземпляр класса B.

Мартин Фаулер предлагает, чтобы ссылка агрегации вообще не использовалась, потому что она не имеет добавленной стоимости и нарушает согласованность, цитируя Джима Рамбо «Думайте об этом как о плацебо моделирования».

Композиция (Неразделенная ассоциация)

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

enter image description here

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

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

Измерительная система сложности

Системный комплекситy можно измерить, просто взглянув на диаграмму классов UML и оценив линии связи, агрегации и композиции. Способ измерения сложности состоит в определении количества классов, на которые может повлиять изменение определенного класса. Если класс A предоставляет класс B, то на любой данный класс, который использует класс A, теоретически могут повлиять изменения в классе B. Сумма числа потенциально затронутых классов для каждого класса в системе равна общей сложности системы.

Вы можете прочитать больше в моем блоге: http://aviadezra.blogspot.com/2009/05/uml-association-aggregation-composition.html


12 голосов
/ 13 июля 2016

Ассоциация

Ассоциация представляет отношения между двумя классами. Она может быть однонаправленной (односторонней) или двунаправленной (двухсторонней)

например:

  1. однонаправленный

Клиент размещает заказы

  1. двунаправленная

А женат на B

B женат на A

Aggregation

Агрегация - это своего рода ассоциация. Но со специфическими особенностями. Агрегирование - это связь в одном большем «целом» классе, содержащем один или несколько меньших классов «частей». "целого" более крупного класса.

например:

В клубе есть члены

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

Состав

Это более сильная форма агрегации. "Целое" отвечает за создание или уничтожение своих "частей"

Например:

В школе есть отделы

В этом случае школа ("целое") должна была умереть, отдел ("части") умрет с этим. Потому что каждая часть может принадлежать только одному «целому».

12 голосов
/ 05 февраля 2016

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

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

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

Насколько я понимаю, эта путаница имеет два корня:

  1. В сообществе C ++ термин «агрегация» использовался в смысле класса, определяющего атрибут для ссылки на объекты другого независимого класса (см., Например, [1]), что означает ассоциация в диаграммах классов UML. Термин «композиция» использовался для классов, которые определяют объекты-компоненты для своих объектов, так что при уничтожении составного объекта эти объекты-компоненты также уничтожаются.

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

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

См. Также мой расширенный ответ на вопрос SO за апрель 2009 года, указанный ниже.

И свойство, которое, как предполагалось, определяло «композицию» между объектами ООП в сообществе C ++ (и это убеждение все еще широко распространено): зависимость жизненного цикла во время выполнения между двумя связанными объектами (составным объектом и его компонентом). ), на самом деле не характерно для «композиции», потому что мы можем иметь такие зависимости из-за целостности ссылок и в других типах ассоциаций.

Например, следующий кодовый код для «композиции» был предложен в SO-ответе :

final class Car {    
  private final Engine engine;

  Car(EngineSpecs specs) {
    engine = new Engine(specs);
  }

  void move() {
    engine.work();
  }
}

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

[1] http://www.learncpp.com/cpp-tutorial/103-aggregation/

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

[ апрель 2009 ]
Агрегация против состава [закрыто как основанное на мнении]
[ апрель 2009 ]
В чем разница между Композицией и Ассоциацией? [ май 2009 ]
Разница между объединением, агрегацией и составом
[ май 2009 ]
В чем разница между составом и агрегацией? [дубликат]
[ окт. 2009 ]
В чем разница между агрегацией, составом и зависимостью? [помечено как дубликат]
[ ноябрь 2010 ]
Ассоциация против агрегации [помечено как дубликат]
[ август 2012 ]
Разница в реализации между Агрегацией и Композицией в Java
[ февраль 2015 ]
UML - ассоциация или агрегация (простые фрагменты кода)

7 голосов
/ 13 марта 2018

Композиция (при удалении «целого» «часть» также удаляется автоматически - «Владение»)

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

  • Обычно используют обычные переменные-члены.

  • Может использовать значения указателя, если класс композиции автоматически обрабатывает распределение / освобождение, ответственное за создание / уничтожение подклассов.

enter image description here

Композиция на С ++

#include <iostream>
using namespace std;
/********************** Engine Class ******************/
class Engine
{
    int nEngineNumber;
    public:
    Engine(int nEngineNo);
    ~Engine(void);
};
Engine::Engine(int nEngineNo)
{
    cout<<" Engine :: Constructor " <<endl;
}
Engine::~Engine(void)
{
    cout<<" Engine :: Destructor " <<endl;
}
/********************** Car Class ******************/
class Car
{
    int nCarColorNumber;
    int nCarModelNumber;
    Engine objEngine;
    public:
    Car (int, int,int);
    ~Car(void);
};
Car::Car(int nModelNo,int nColorNo, int nEngineNo):
nCarModelNumber(nModelNo),nCarColorNumber(nColorNo),objEngine(nEngineNo)
{
    cout<<" Car :: Constructor " <<endl;
}
Car::~Car(void)
{
    cout<<" Car :: Destructor " <<endl;
    Car
    Engine
    Figure 1 : Composition
}
/********************** Bus Class ******************/
class Bus
{
    int nBusColorNumber;
    int nBusModelNumber;
    Engine* ptrEngine;
    public:
    Bus(int,int,int);
    ~Bus(void);
};
Bus::Bus(int nModelNo,int nColorNo, int nEngineNo):
nBusModelNumber(nModelNo),nBusColorNumber(nColorNo)
{
    ptrEngine = new Engine(nEngineNo);
    cout<<" Bus :: Constructor " <<endl;
}
Bus::~Bus(void)
{
    cout<<" Bus :: Destructor " <<endl;
    delete ptrEngine;
}
/********************** Main Function ******************/
int main()
{
    freopen ("InstallationDump.Log", "w", stdout);
    cout<<"--------------- Start Of Program --------------------"<<endl;
    // Composition using simple Engine in a car object
    {
        cout<<"------------- Inside Car Block ------------------"<<endl;
        Car objCar (1, 2,3);
    }
    cout<<"------------- Out of Car Block ------------------"<<endl;
    // Composition using pointer of Engine in a Bus object
    {
        cout<<"------------- Inside Bus Block ------------------"<<endl;
        Bus objBus(11, 22,33);
    }
    cout<<"------------- Out of Bus Block ------------------"<<endl;
    cout<<"--------------- End Of Program --------------------"<<endl;
    fclose (stdout);
}

выход

--------------- Start Of Program --------------------
------------- Inside Car Block ------------------
Engine :: Constructor
Car :: Constructor
Car :: Destructor
Engine :: Destructor
------------- Out of Car Block ------------------
------------- Inside Bus Block ------------------
Engine :: Constructor
Bus :: Constructor
Bus :: Destructor
Engine :: Destructor
------------- Out of Bus Block ------------------
--------------- End Of Program --------------------

Агрегация (если вы удалите «целое», «Часть» может существовать - «Нет собственности»)

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

  • Обычно используют переменные-указатели / ссылочные переменные, которые указывают на объект, который находится вне области действия агрегатного класса

  • Может использовать ссылочные значения, которые указывают на объект, который находится вне области действия агрегатного класса

  • Не несет ответственности за создание / уничтожение подклассов

enter image description here

Код агрегации в C ++

#include <iostream>
#include <string>
using namespace std;
/********************** Teacher Class ******************/
class Teacher
{
    private:
    string m_strName;
    public:
    Teacher(string strName);
    ~Teacher(void);
    string GetName();
};
Teacher::Teacher(string strName) : m_strName(strName)
{
    cout<<" Teacher :: Constructor --- Teacher Name :: "<<m_strName<<endl;
}
Teacher::~Teacher(void)
{
    cout<<" Teacher :: Destructor --- Teacher Name :: "<<m_strName<<endl;
}
string Teacher::GetName()
{
    return m_strName;
}
/********************** Department Class ******************/
class Department
{
    private:
    Teacher *m_pcTeacher;
    Teacher& m_refTeacher;
    public:
    Department(Teacher *pcTeacher, Teacher& objTeacher);
    ~Department(void);
};
Department::Department(Teacher *pcTeacher, Teacher& objTeacher)
: m_pcTeacher(pcTeacher), m_refTeacher(objTeacher)
{
    cout<<" Department :: Constructor " <<endl;
}
Department::~Department(void)
{
    cout<<" Department :: Destructor " <<endl;
}
/********************** Main Function ******************/
int main()
{
    freopen ("InstallationDump.Log", "w", stdout);
    cout<<"--------------- Start Of Program --------------------"<<endl;
    {
        // Create a teacher outside the scope of the Department
        Teacher objTeacher("Reference Teacher");
        Teacher *pTeacher = new Teacher("Pointer Teacher"); // create a teacher
        {
            cout<<"------------- Inside Block ------------------"<<endl;
            // Create a department and use the constructor parameter to pass the teacher to it.
            Department cDept(pTeacher,objTeacher);
            Department
            Teacher
            Figure 2: Aggregation
        } // cDept goes out of scope here and is destroyed
        cout<<"------------- Out of Block ------------------"<<endl;
        // pTeacher still exists here because cDept did not destroy it
        delete pTeacher;
    }
    cout<<"--------------- End Of Program --------------------"<<endl;
    fclose (stdout);
}

Выход

--------------- Start Of Program --------------------
Teacher :: Constructor --- Teacher Name :: Reference Teacher
Teacher :: Constructor --- Teacher Name :: Pointer Teacher
------------- Inside Block ------------------
Department :: Constructor
Department :: Destructor
------------- Out of Block ------------------
Teacher :: Destructor --- Teacher Name :: Pointer Teacher
Teacher :: Destructor --- Teacher Name :: Reference Teacher
--------------- End Of Program --------------------
...