Aggregation versus Composition

Viewed 84959

I've had a hard time understanding the difference between composition and aggregation in UML. Can someone please offer me a good compare and contrast between them? I'd also love to learn to recognize the difference between them in code and/or to see a short software/code example.

Edit: Part of the reason why I ask is because of a reverse documentation activity that we're doing at work. We have written the code, but we need to go back and create class diagrams for the code. We'd just like to capture the associations properly.

12 Answers

The distinction between aggregation and composition depends on context.

Take the car example mentioned in another answer - yes, it is true that a car exhaust can stand "on its own" so may not be in composition with a car - but it depends on the application. If you build an application that actually has to deal with stand alone car exhausts (a car shop management application?), aggregation would be your choice. But if this is a simple racing game and the car exhaust only serves as part of a car - well, composition would be quite fine.

Chess board? Same problem. A chess piece doesn't exist without a chess board only in certain applications. In others (like that of a toy manufacturer), a chess piece can surely not be composed into a chess board.

Things get even worse when trying to map composition/aggregation to your favorite programming language. In some languages, the difference can be easier to notice ("by reference" vs. "by value", when things are simple) but in others may not exist at all.

And one last word of advice? Don't waste too much time on this issue. It isn't worth it. The distinction is hardly useful in practice (even if you have a completely clear "composition", you may still want to implement it as an aggregation due to technical reasons - for example, caching).

Composition implies that the child objects share a lifespan with the parent. Aggregation doesn't. For example, a chess board is composed of chess squares - the chess squares don't really exist without the board. However, a car is an aggregation of parts - a car exhaust is still a car exhaust if it's not part of a car at the time.

The example I learned was fingers to the hand. Your hand is composed of fingers. It owns them. If the hand dies, the fingers die. You can't "aggregate" fingers. You can't just go grab extra fingers and attach and detach them from your hand at will.

The value here, from a design viewpoint, is often related to object lifespan as another poster said. Say you have a Customer and they have an Account. That Account is a "composed" object of the customer (at least, in most contexts I can think of). If you delete the Customer, the Account has no value on it's own so it would be deleted as well. The reverse is often true on object creation. Since an Account only has meaning in the context of a Customer, you'd have Account creation occur as part of Customer creation (or, if you do it lazily, it'd be part of some Customer transaction).

It's useful in design to think about what objects own (compose) other objects vs. ones that just reference (aggregate) other objects. It can help determine where the responsibility lies for object creation/cleanup/updates.

As far as in the code, it's often hard to tell. Most everything in code is an object reference so it may not be obvious whether the referenced object is composed (owned) or aggregated.

In code terms, composition usually suggests that the containing object is responsible for creating instances of the component*, and the containing object holds the only long-lived references to it. So if the parent object gets de-referenced and garbage-collected, so will the child.

so this code...

Class Order
   private Collection<LineItem> items;
   ...
   void addOrderLine(Item sku, int quantity){
         items.add(new LineItem(sku, quantity));
   }
}

suggests that LineItem is a component of Order - LineItems have no existence outside of their containing order. But the Item objects aren't constructed in the order - they're passed in as needed, and continue to exist, even if the shop has no orders. so they're associated, rather than components.

* n.b. the container is responsible for instanciating the component, but it might not actually call new...() itself - this being java, there's usually a factory or two to go through first!

The conceptual illustrations provided in other answers are useful, but I'd like to share another point I've found helpful.

I've gotten some mileage out of UML for code generation, for source code or DDL for relational database. There, I have used composition to indicate that a table has a non-nullable foreign key (in the database), and a non-nullable "parent" (and often "final") object, in my code. I use aggregation where I intend a record or object to be able to exist as an "orphan", not attached to any parent object, or to be "adopted" by a different parent object.

In other words, I've used the composition notation as a shorthand to imply some extra constraints that might be needed when writing code for the model.

The example that I like: Composition: Water is a part-of a Pond. (Pond is a composition of water.) Aggregation: Pond has ducks and fish (Pond aggregates ducks and fish)

As you can see I have bolded "part-of" and "has", as these 2 phrases can typically point to what kind of a connection exists between the classes.

But as pointed out by others, many times whether the connection is a composition or an aggregation depends on the application.

Related