In addition to being directed or bidirectional, associations
may be aggregations or compositions. These special classifications
provide more information about the association.
A solid diamond on the composing class’ side of the
association indicates composition, as indicated in the diagram. If that diamond were hollow, the association
would be an aggregation. The next
section contains more information about aggregations.
In many books, you read that compositions create
containment. The composing object
contains the composed object. While this
description is true, it doesn't help explain the composition relationship or
how to use it. An alternative explanation
is that a composing object “has a” composed object, as in “TimeBasedDetector
has a Timer.” Now, this “has a” description also works for
aggregations. So what is the difference
and is it important?
The basic difference between aggregations and compositions has
to do with where the objects are created.
In an aggregation, the object is created elsewhere in the model. The links between objects get set during a
post-instantiation/pre-runtime setup phase.
For composition associations, the composed object creates and destroys
the composed objects. It also must
configure the link relationships.
Typically, one configures composition relations during instantiation, as
shown in the code snippet below.
//##
class TimeBasedDetector
public
class TimeBasedDetector implements GenericDetector {
protected int LastSensorValue;
protected Timer itsTimer; //## link itsTimer
// Constructors
public
TimeBasedDetector() {
initRelations();
}
//Called by constructor to create the timer
composition and configure the links
protected void initRelations() {
itsTimer = newItsTimer();
}
// Construct the timer
public Timer newItsTimer() {
itsTimer = new Timer();
itsTimer._setItsDetector(this);
//configures the Timer’s link to point here
return itsTimer;
}
//Configures the link
public void _setItsTimer(Timer p_Timer) {
if(itsTimer != null)
{
itsTimer.__setItsDetector(null);
}
__setItsTimer(p_Timer);
}
//configures the link
public void __setItsTimer(Timer p_Timer) {
itsTimer = p_Timer;
}
// Destructor
//## operation ~TimeBasedDetector()
protected void finalize() throws Throwable
{
cleanUpRelations();
//#[ operation ~TimeBasedDetector()
//#]
super.finalize();
}
//called to delete the composed class
protected void cleanUpRelations() {
{
deleteItsTimer();
}
}
//sets the links to null so that the trash
collection runs
public void deleteItsTimer() {
itsTimer.__setItsDetector(null);
itsTimer=null;
}
When we look at aggregation relationships, we’ll see that
the construction/destruction of aggregated objects is not handled by the
aggregating object. Therefore, the
difference between the two is very important for describing how the developers
build the code.