Aggregation and Qualification

Recall that the endpoint of an association can be decorated by:

name

multiplicity (1, 1..3, *, etc.)

navigability (true or false)

scope (public +, private -, protected #, package ~)

We can think of these as properties of an association endpoint. We can see this clearly in the UML meta-model:

Endpoints have additional properties we consider here:

Aggregation: none, aggregation, composition

Qualifiers

Ownership: instance or class (i.e., static)

Ordering: ordered or unordered

Changability: changeable, frozen, add-only

Aggregation

A common relationship in domains is membership:

Element X is a member of Collection Y.

For example:

Athelete X is a member of Team Y.

Computer X is a member of Network Y.

Event X is a member of Schedule Y.

City X is a member of Route Y.

Vehicle X is a member of Fleet Y.

There are several important properties of the membership relation:

Members of a collection can be shared by other collections. For example, a city can be a member of several routes. An athelete can be a member of several teams. (Neon Dion was a membr of a baseball team and a football team.)

Destroying a collection doesn't destroy the elements. For example, if a network crashes, it doesn't mean that the computers crash. Disbanding a team doesn't mean that the atheletes must retire.

Removing an element doesn't impair the collection. For example, removing a computer from a network doesn't impair the network. Of course this point is debatable. Removing a good athletee from a team may impair the team's ability to win games, but we are only talking about the ability of a collection to store elements.

We can represent membership relations as ordinary association, but if we want to emphasize that the relationship is a membership, we can decorate the collection side of the association with a hollow diamond indicating that the collection side is an aggregation:

Note that the "many" multiplicity (*) on the aggregation side is implied.

It is possible to have other multiplicities on the element side.

For example, some modelers use aggregation to simply show that an associated object is shared or held "by reference":

Ordering and Uniqueness

A collection can be ordered or unordered. For example, Team and Fleet are unordered collections, while Schedule and Route are ordered collections. Depending on the technology, a Network might be either. If ordered, the elements can be ordered naturally or

The elements in a collection can be unique or not. For example, the same event (check exchange rate, for example) might occur multiple times in a schedule. However, the computers in a network are unique, the athletes on a team are unique, and the vehicles in a fleet are unique.

Here is the terminology:

collections

unordered

ordered

unique elements

set

ordered set

non-unique elements

multiset

sequence

Implementation

Here's a hypothetical implementation hierarchy:

A collection usually provides support for adding, removing, and searching for members. It also provides support for iterating through the members:

class Collection {
   void add(Element e) {
      // add e to this collection
   }
   void remove(Element e) {
      // remove e from this collection
   }
   boolean member(Element e) {
      // return true if e is in this collection
   }
   int size() {
      // returns the size of this collection
   }
   Iterator getIterator() {
      // return an iterator or this collection
   }
}

An iterator allows a user to visit each element in the collection:

class Iterator {
   private Collection myCollection;
   Element next() {
      // return next unseen element in myCollection
   }
   void reset() {
      // make all elements of myCollection unseen
   }
   int hasNext() {
      // return true if there are unseen elements in myCollection
   }
}

A set is just a collection that doesn't allow non-unique elements:

class Set exends Collection {
   void add(Element e) {
      if (!member(e)) {
         super.add(e);
      }
   }
}

An ordered set assumes there is some way to compare its elements:

class OrderedSet exends Collection {
   void add(Element e) {
      if (!member(e)) {
         // add e to the immediate right of all "smaller" elements
      }
   }
}

A sequence is a collection that adds support for positioning elements:

class Sequence extends Collection {
   void add(Element e, int pos) {
      // add e to this sequence at position pos
   }
   void remove(int pos) {
      // removes element at position pos in this sequence
   }
   int position(Element e) {
      // returns position of element e in this sequence
   }
   Element get(int pos) {
      // returns the element at position pos in this sequence
   }
}

Internally, the elements might be stored in an array, linked list, or tree-like data structure.

Queues and Stacks are special types of collections.

Composition

Another common relationship in domains is part-of:

Component X is a part of Assembly Y.

For example:

Microchip X is part of Computer Y.

Button X is part of Control Panel Y.

Term X is part of Equation Y.

There are several important properties of the part-of relationship that help distinguish it from the membership relation:

Components of an assembly are not shared by other assemblies. For example, a particular microchip isn't shared (simultanelously) by several computers.

Destroying an assembly destroys the components. For example, if a computer is crushed by a steamroller, then its microchips are also crushed.

Removing a component impairs the functionality of the assembly. For example, removing the CPU will impair a computr's ability to excute programs.

We can represent the part-of relations as ordinary association, but if we want to emphasize that the relationship is a part-of relationship, we can decorate the assembly side of the association with a solid diamond indicating that the assembly side is a composition:

Note that the implied multiplicity on the assembly side is one, components aren't shared.

The multiplicity on the component side is varied.

Implementation

Classes in C++ can distinguish between holding an object by value or by reference:

class Computer {
   Microchip cpu;
   // etc.
};

class Event {
   Date& time;
};

In Java all objects are held by reference.

Complications

While UML allows us to distinguish between aggregation and composition, there are many more of these relationships for which UML has no special notation. See Types of Aggregation for details.

Qualifiers

If the multiplicity of an endpoint is more than one, then how are the associated objects are distinguished?

For example, a triangle contains three vertices:

How will these vertices be distinguished? Vertex 1, 2, and 3? Vertex 0, 1, and 2? Vertex A, B, and C?

Of course we could have specified their names if we used three associations instead of one:

UML allows us to specify how to name multiple associated objects by adding a qualifier to the opposite endpoint of the association:

In this example we may infer that the three points are distinguished by integer indices beginning with 0. Here's a possible implementation:

class Triangle {
   Point[] vertices = new Point[3];
   Point vertex(int i) {
      if (i < 0 || 2 <  i) {
         return null;
      }
      return vertices[i];
   }
   // etc.
}

We can index objects by any type. In this example a business directory (like the Yellow Pages) indexes retailers by their business (e.g., auto sales, vacuum repair, fortune teller, etc.):

We might use a hash table to implement this:

class Directory {
   Hashtable<Business, Retailer> registry;
   Retailer search(Business b) {
      return regisgtry.get(b);
   }
   void register(Business b, Retailer r) {
      registry.put(b, r);
   }
}