Composition is the strongest has-a relationship. The whole is made of its parts and is responsible for them: it creates them, uses them and lets them die with it.
Composition is a stronger form of "has-a": the whole owns its parts, and the parts cannot exist without the whole. When the whole is destroyed, its parts are destroyed too. It is a "part-of" relationship.
Examples: a House has Rooms; a Book has Chapters; a Car has an Engine; an Order has OrderLines.
class Engine {
private int power;
Engine(int power) { this.power = power; }
void start() { System.out.println("Engine " + power + "hp started"); }
}
class Car {
private final Engine engine; // part owned by the car
Car(int power) {
this.engine = new Engine(power); // part CREATED INSIDE the whole
}
void drive() { engine.start(); System.out.println("Car moving"); }
}
Car c = new Car(150);
c.drive();
// no way for outside code to hold or reuse that Engine; when c is
// collected, its Engine goes with itKey code pattern: the part is created inside the whole's constructor and not shared with the outside.
Reading the Car example
- The
Engineis created inside the Car constructor withnew Engine(power). No outside code ever has a reference to it. - The
engineattribute isprivate final: it is hidden, and it can never be swapped for another engine object. - When
drive()is called, the car delegates part of the work to its engine:engine.start(). The outside world only talks to the Car. - When the Car object becomes unreachable, its Engine is unreachable too, so both are collected. The part lives and dies with the whole.
Do not leak the parts
Composition only works if the whole keeps its parts to itself. If a class creates a part and then hands out a reference to it, outside code can hold on to the part, change it or share it, and the "owned" relationship is broken:
class Order {
private final List<OrderLine> lines = new ArrayList<>();
void addLine(String product, int qty, double price) {
lines.add(new OrderLine(product, qty, price)); // created inside
}
List<OrderLine> getLines() {
return Collections.unmodifiableList(lines); // read-only view
}
}The order creates its own lines from plain values, and it only returns a read-only view of the list, so nobody else can add or remove lines.
Composition over inheritance
A famous design rule says: prefer composition to inheritance. Inheritance ties the subclass tightly to its parent, because a change in the parent affects every subclass, and a class can only extend one parent. Composition is more flexible: a Car can have an Engine, a GPS and a Radio, and each part can be designed, tested and replaced on its own. Use inheritance only for a real is-a relationship, and use composition for everything that is a part of something else.
| Question | Inheritance | Composition |
|---|---|---|
| Relationship | is-a (a Car is a Vehicle) | has-a / part-of (a Car has an Engine) |
| How it is written | class Car extends Vehicle | private final Engine engine = new Engine(...) |
| Number allowed | One parent class | As many parts as needed |
| Flexibility | Fixed when the code is compiled | Parts can be designed and changed separately |
Remember
- Composition: the whole creates and owns its parts, and they die with it.
- Create the parts inside the whole, keep them private, and do not hand them out.
- UML: a filled diamond at the whole.