All,
This is my understanding...
1. Association (represented by a line between two classes, optionally an arrowhead represents direction): This is the weakest form of reference. I like to compare this with global variables or static members. If an object got a reference to a singleton, I would call that association. When the calling object goes out of scope, the singleton is still available for use by other clients.
2.Aggregation - stronger form of association (represented by a hollow diamond on the non-arrowhead side of the line): In aggregation, the instances of one class share a reference to the instance of the referenced class. In some programming languages, this is represented by shared variables.
Non-software example: Assume two circles are intersecting each other. At the point of intersection, the point is being shared by the two circles. If one circle goes out of scope, the point does not.
Good s/w example is when you use the prototype
pattern and do "shallow cloning." When the prototypical object is cloned, the object references are shared.
3. Composition: Strongest form of association. Also a whole-part relationship (represented with a solid diamond on the non-arrowhead side): Here the instance of the reference belongs to the instance of the instantiator. Best examples are instance variables created by the instantiator (not just obtaining a reference to an object.)
A good example is "deep copy" using the prototype pattern. Each prototypical instance has it's own instances of object references.
HTH.