The difference between composition and aggregation is related to the existence of objects. This difference is not addressed by the object-oriented programming languages (at least not conventional ones: java, c#, c++).
Every time we have composition, it means the part does not exist without the whole.
Every time we have aggregation, it means that the part can be shared between several objects.
Object orientation or UML?
Aggregation behavior does not belong exclusively to the object-oriented paradigm. We have the same behavior in the imperative paradigm. This is the case for C-shaped structures. See an example:
struct Person
{
int age;
char *name;
enum { male, female } sex;
};
age, name and sex make up the Person type
struct bintree
{
struct bintree *left, *right;
// some data
};
bintree is composed of left and right, which are bintree. Reflective composition.
See the concept of composition described in several languages that are not object-oriented in wikipedia.
Types of association in UML
When we speak of aggregation and composition We are talking about special cases of types of class association. There are, in UML, associations: simple, aggregation, generalization, dependence, realization (and there must be others that I don’t remember now).
The type of association aggregation can be classified basically in two ways: aggregation of composition and shared aggregation (or reflective).
Aggregations
These types of relations are so called because they add value to the related object. This is a specialized type of association that allows us to face the relationship between objects as: Whole/Part.
Whole/Part means that one side of the association (a class) is called All and the other side is called Part, since the part allows us to think that: A Part is contained in the All.
Composition (or aggregation of composition)
Every time we say that the relationship between two classes is composition we are saying that one of these classes (the Party) is contained in the other (the Whole) and the part does not live/does not exist without the whole.
Therefore, every time we destroy the whole, the part that is unique and exclusive of the whole goes together. For this reason no one says that: the part is contained all in all. When you throw the whole out, the part was in and goes along.
Aggregation (or shared aggregation)
This is also a whole/part relationship, but in this case we say that the part is shared by others (hence shared aggregation). That means the part of a guy A
is contained in a type B
, when this has aggregation relationship between them, however, that same part A
does not exist only for compose B
, that party may aggregate other types.
In short
We have established what are composition and shared aggregations, now that the names make sense we can exemplify as follows:
- Composition (Aggregation of composition)
There must be at least one item in a tax note for the tax note to exist.
Soon: Notafiscal is composed of Itemnotafiscal.
- Aggregation (shared aggregation)
If I have a team registration system, I need several people to join the teams, so each person can add a team, no team, or several teams. The person is independent of the team, but adds value to it.
Soon: Time is aggregated by Person.
There is no difference in implementation but in behavior
In both types of relation there is no difference at the time of implementation, see an example in C#:
Composition
class NotaFiscal: IDisposable {
IList<ItemNotaFiscal> Itens {get;set;}
}
class ItemNotaFiscal: IDisposable { ... }
Aggregation
class Time {
IList<Pessoa> Integrantes {get;set;}
}
class Pessoa {}
However, the behaviors semantics associations must be present for their existence. For composition, for example, we could force that every time a note is created, a new list of Itemnotafiscal should be created. And every time the invoice is deleted, the items must be destroyed.
class NotaFiscal {
IList<ItemNotaFiscal> Itens {get;set;}
NotaFiscal(){
// Cria lista nova
Itens = new List<ItemNotaFiscal>();
}
void Dispose() {
foreach(var item in Itens){
item.Dispose();
}
}
}
Thus, the items will be destroyed along with the invoice.
Aggregation would not require such object creation and destruction treatment. Since the parties can be shared.
Aggregations and multiplicity are different
Many think that every time there is an aggregation/composition we will have a list/part array, however, what tells us if we will have more than one associated type is multiplicity and not the kind of association. Regardless of the type of association, the multiplicity can be: 0.1,* or n..m. So, every time an association is 1 to 1, we have no lists on either side.
Take an example:
class Carro
{
Motor UnicoEExclusivoMotor {get;set;}
}
class Motor{}
In that case, the Motor
is unique and exclusive to the Carro
, and every time Carro
is destroyed, the Motor
will also be destroyed.
This deception occurs because most often when an object is related to a collection of other objects, this association expresses one of the types of aggregation. Aggregation associations where no collections occur are unusual because of this.
Completion
Aggregation or composition are a type of relationship between two objects/types. Each of the types of association is related to the behavior between the objects and to their existence according to the whole/part concept.
Aggregations have nothing to do with multiplicity. Although, most often, objects associated with a collection of other objects express, in their relationships, an aggregation behavior.
I took the opportunity to write an article on the subject in https://www.anmaia.com.br/posts/composicao-e-agregacao-tem-diferenca
– anmaia