Aggregation and Composition are class relationships that
define classes with a "part-whole" relationsihp: where one
class is part of another, or one class is contained inside
another. It's a very common relationship but it does
mean that there is a strong dependency between the two
classes. This lesson looks at aggregation and composition
in more detail, including the important differences between
the two.
Pre-Requisites
It is assumed that you've gone over the
Introduction to Class Relationships
lesson and are already somewhat familiar with Dependency and
Association.
Aggregation
Aggregation and Composition are types of Association, and
are stronger forms of dependency than Association. The
difference between Aggregation and Composition has to do with
the life cycle of the "part" object in relation to the "container"
or "whole" object. It makes the most sense to talk about
Aggregation, first.
Aggregation is a stronger form of Association in that
it involves ownership: ClassA (the "whole" or "container")
contains or owns ClassB (the "part"). The containing class (ClassA) "owns"
the part class (ClassB). ClassB is part of the state
of ClassA, just like in association. The main difference
is that the aggregation is not bi-directional: it's uni-directional.
In other words, the "action" goes in only one direction.
For example, in a role playing game you might have a Player and a
Weapon class:
public class Player {
private String name;
private String playerClass;
private Weapon[] weapons;
public void armPlayer(Weapon w) { ... }
}
Weapon
- name : String
- damage : int
public class Weapon {
private String name;
private int damage;
}
In the above example, a Player can have some weapons
(i.e. a Player could own a broad sword, a dagger, and a
crossbow), and
can arm themselves with one of those weapons and fight with it.
The Player class contains
a list of Weapon objects that player owns.
A Weapon can belong to a Player, and can even change ownership
and belong to a different Player. However, a Weapon can only
belong to one player at a time (or no player, if the weapon
is discarded). There is clear ownership here: The Weapon
belongs to a Player, when it is owned by someone.
What makes this a uni-directional Aggregation relationship
is that the Player class "knows about" (has a reference to) the
Weapon but the Weapon doesn't "know about" the Player class (there
is no Player data member in the Weapon class). If this were
an association relationship, the Weapon class would contain a
reference to the Player that owns it.
A Weapon can exist without any Player
as owner (e.g. if the Weapon is dropped or discarded by
a Player) and a Player can exist without owning any weapon
at all. This is also an important characteristic of Aggregation:
The part can exist without the whole/container and vice versa.
In an Aggregation relationship, the two objects can exist independent of each other
and have their own life cycles.
There is ownership, but removing the part doesn't
cause a removal of the whole, and vice versa. For example, deleting a Player
doesn't cause a deletion of the Weapon, and vice versa.
Additionally,the parts can be parts of more than one thing:
they're not exclusive. For example, a Weapon can
be owned by different Players (Players could share a weapon, they
just couldn't use it at the same time).
Here is another common example:
a Car class and an Engine class are two completely different
classes, but a Car has an Engine. Both Car and Engine
have their own
attributes and methods, but Car might include an attribute for
the Engine object -- a Car owns an Engine. That
Engine could be taken out of that Car and put into another Car,
or the Engine could be taken out of the Car and put into
inventory to wait for another Car that might need that Engine.
Also, the Car owns the Engine, but the Engine doesn't own
the Car.
Car
- model : String - year : int engine : Engine
currentGasQty : double
Notice that the context in the above example was inventory:
Perhaps parts inventory in an auto shop. If the context were
different, then the class relationship between Car and Engine
might be different. For example, if this were a racing game
where the car needs the Engine in order to accelerate and
decelerate, this would be a stronger form of Aggregation called
Composition.
Composition
Composition is a stronger form of Aggregation. In a Composition relationship,
the part is exclusive to the container -
it can't belong to more than one container or whole.
For example, a House object can contain many Room objects, but a Room
object can only belong to one House.
Additionally, with composition the part can't exist without the whole, and the life cycle
of the part is completely dependent upon the life cycle of the whole. When
the House is created, the Room is created with it. When the House is
destroyed, the Room is destroyed with it (you can't pick up a Room and put
it into another House).
Another example might be Student and Name: A Student owns or contains Name.
A Name can't exist on its own: you can't have a Name in your
database without belonging to a Student. If you delete a Student, the Name is also
deleted. A Name can only belong to one Student (Students that happen to have the exact same
Name still don't share the same Name object).
public class Student {
private Name name;
private Address address;
private String phoneNumber;
public Student() { ... }
public void setName(String first, String middle, String last) {
name = new Name(first, middle, last);
}
public String getName() {
return name.getLastName() + ", " + name.getFirstName()
+ " " + name.getMiddleName();
}
}
In the example above, a Student owns a Name object.
Notice that the getName() method doesn't actually return
a Name object and setName() doesn't accept a Name object
as an argument. The Name object is completely
encapsulated inside the Student class: in a true composition
relationship, there should be no access to the part object
outside of the container class. In this example, there
is no access to the Student's name object outside of the
Student class.
This shows the strong dependency of the part's life cycle
on the container's life cycle: The Name object is only
created when the Student object is created. When the
Student object is destroyed, the Name object that belongs
to that Student is also destroyed, as there are no other
references to it outside of the Student class.
Aggregation and Composition in UML
Aggregation is shown with a solid line and a hollow diamond at the end of the line that
connects the "whole" or "container" part of the relationship. Composition is similar, but
with a solid diamond. Example:
Exercise
Imagine an application for a ride-sharing application that
has a Map, Drivers, Customers, Trips, Origins, and Destinations.
Where would there be aggregation or composition between classes in the
application? Describe each instance of aggregation and composition.