48

I'm confused about some of the notations of UML class diagrams.

enter image description here

Pretty sure I know what Association means. Any relationship between instances of two classes, where an instance of one class needs to know about an instance of the second class in order to perform it's work - is an Association relationship. An Association often means class A has a reference (field) to an instance of class B.

However, I'm having trouble understanding what the Aggregation and Composition arrows mean. Part of my confusion was caused by encountering different definitions of these notations.

Two definitions of the Aggregation notation:

Definition 1: An Aggregation notation between two classes is suitable whenever an instance of class A holds a collection of instances of class B (e.g. a List, Array, whatever).

Definition 2: An Aggregation link between two classes is suitable if an instance of class A holds a reference to an instance of class B, and the B instance is dependent on the lifecycle of the A instance. Meaning: When the instance of class A get's deleted, so will the instance of class B. The instance of class B is entirely contained by the instance of class A, as opposed to the instance of class A simply owning a reference to the instance of class B (which is regular Association).

Regarding what the Composition notation means and how it differs from the Aggregation notation, I'm not sure.

Please clarify the definitions and help me understand. Concrete examples would be welcome.

1
  • Definition 2 sounds more like the definition for Composition rather than Aggregation. Definition 1 sounds quite right.
    – jbx
    Commented Oct 10, 2015 at 0:53

4 Answers 4

35

The three links Association, Aggregation and Composition form a kind of scale on how closely two classes are related to each other.

On the one end of the scale, there is Association, where objects of the two classes can know about each other, but they do not affect each others lifetime. The objects can exist independently and which class A object knows about which class B objects can vary over time.

On the other end of the scale, there is Composition. Composition represents a part -- whole relationship such that class B is an integral part of class A. This relationship is typically used if objects of class A can't logically exist without having a class B object.

The Aggregation relation is somewhere between those two ends, but nobody seems to agree where exactly, so there is also no universally agreed definition of what an Aggregation means. In that sense, both definitions that you found are correct and if you ask 10 people, you risk getting 11 different definitions.

7
  • 1
    Thanks for your answer. Here's how I understand things, please say if this is a reasonable definition. 1- Association is whenever an A object needs to know about a B object to perform it's functionality. 2- Both Aggregation and Composition define an 'ownership' relationship - an instance of class A conceptually owns an instance of class B. But the lifetime of the B instance is independent of the lifetime of the A instance. For example, a department with employees. The department 'owns' שמ employee instance, but it'll keep on living without the department. Composition is like Aggregation, but
    – Aviv Cohn
    Commented Apr 9, 2014 at 11:44
  • 1
    the B instance's lifetime is dependent on the A instance's lifetime. A stronger 'ownership' relationship. For example: A car and a wheel. The car 'entirely contains' the wheel. The Wheel instance won't continue living without the Car instance containing it. Is this a reasonable differentiation?
    – Aviv Cohn
    Commented Apr 9, 2014 at 11:45
  • @Prog: Yes, that is a reasonable definition. Just remember that others may not share that definition and that you might need to explain your use of aggregation to them. Commented Apr 9, 2014 at 12:03
  • What would you say is the most common definition for the Aggregation notation? The definition I'm using? The 'has a collection of' definition? Something else?
    – Aviv Cohn
    Commented Apr 9, 2014 at 17:54
  • The reference to the OMG standard below is instructive. Association and composition are fairly straightforward. Aggregation is the wobbly one. In practice, I find that the 'part of' test is works well ('ownership' is a sub-optimal way to think about it). A person can be part of a club, thus a club aggregates people (it does not own them). When the club is destroyed the people continue to exist.
    – Huliax
    Commented Jun 22, 2016 at 15:31
12

Composition is when an object A contains object B and the object A is also responsible for creating the object B.

Composition relationship

We have a class A which will be used by class B.

final class A
{
}

There are multiple options as how the composition may look.

Direct initialization composition:

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

Constructor initialization composition

final class B
{
    private $a;

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

Lazy initialization composition

final class B
{
    private $a = null;

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

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

You see this creates a tight relationship between the classes A and B. Class B simply cannot exists without A. This is a huge violation of dependency injection principle, which says:

A dependency is an object that can be used (a service). An injection is the passing of a dependency to a dependent object (a client) that would use it. The service is made part of the client's state. Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.

Composition sometimes makes sense, such as calling new DateTime in php or new std::vector<int> in C++. But more often than not, it is a warning, that your code design is wrong.

In a case, where the class A would be a special object used to caching, the class B would always be cached using the implementation of class A, and you would have no control to dynamically change it, which is bad.

Also, if you used the lazy initialization composition, meaning you would have a working object B, called the useA() method and the creation of object A would fail, your object B is suddenly useless.


Aggregation, on the other hand, is a way of relationship, which follows the DI principle. object B needs to use object A, then you should pass already created instance of object A to object B, and should the creation of object A fail, nothing would be passed in the first place.

In short, Aggregation is UML representation for dependency injection principle, be it constructor injection, setter injection or public property injection.

These are all Aggregations

The tightest, constructor injection (object B cannot exists without object A).

final class B
{
    private $a;

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

Looser (you may or may not use object A inside object B, but if you do, you should probably set it first).

Via setter:

final class B
{
    private $a;

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

Via public property:

final class B
{
    public $a;
}

There isn't really a great way to justify the usage of Aggregation over Composition, if all you are using are concrete implementations of classes, but once you start injecting interfaces or in case of C++ abstract classes, suddenly Aggregation will be the only way to fulfill your contract.

1
  • 2
    Seeing code examples really helps! Explanations in English without code all seem so vague and subjective. Commented Jun 25, 2016 at 17:37
2

In addition an excerpt of the current UML standard:

11.5.4 Associations – Semantics – Notation

[...] A binary Association may have one end with aggregation = AggregationKind::shared or aggregation = AggregationKind::composite. When one end has aggregation = AggregationKind::shared a hollow diamond is added as a terminal adornment at the end of the Association line opposite the end marked with aggregation = AggregationKind::shared. The diamond shall be noticeably smaller than the diamond notation for Associations. An Association with aggregation = AggregationKind::composite likewise has a diamond at the corresponding end, but differs in having the diamond filled in. […]

9.5.4 Classification – Properties – Notation

[…] Sometimes a Property is used to model circumstances in which one instance is used to group together a set of instances; this is called aggregation. To represent such circumstances, a Property has an aggregation property, of type AggregationKind; the instance representing the whole group is classified by the owner of the Property, and the instances representing the grouped individuals are classified by the type of the Property. AggregationKind is an enumeration with the following literal values:

  • none: Indicates that the Property has no aggregation semantics.
  • Shared: Indicates that the Property has shared aggregation semantics. Precise semantics of shared aggregation varies by application area and modeler.
  • Composite: Indicates that the Property is aggregated compositely, i.e., the composite object has responsibility for the existence and storage of the composed objects (see the definition of parts in 11.2.3). Composite aggregation is a strong form of aggregation that requires a part object be included in at most one composite object at a time. If a composite object is deleted, all of its part instances that are objects are deleted with it.

[…]

0

I already have posted an answer on Stackoverflow.

Basically, an aggregation is stronger than a simple association but aggregated objects can go on "living" without each other as with a simple association.

A composition is even stronger than an aggregation because the aggregated class cannot be aggregated by other classes. Its "life" depends on the container.

Not the answer you're looking for? Browse other questions tagged or ask your own question.