Composition
Has-a relationship (strong)
Overview
Composition is a strong form of aggregation representing a "has-a" relationship with strong ownership. The contained objects (parts) cannot exist independently of the container (whole). When the whole is destroyed, the parts are destroyed too.
This is the strongest form of association between objects.
Key Concepts
Strong "has-a" relationship
Parts cannot exist without the whole
Parts are created and managed by the whole
Represented by filled diamond in UML
Lifecycle dependent - deleting whole deletes parts
Code Example
1// Composition: House has Rooms
2// Rooms cannot exist without the House
3
4public class Room {
5 private String name;
6 private double area;
7
8 // Package-private or created by House
9 Room(String name, double area) {
10 this.name = name;
11 this.area = area;
12 }
13
14 public void display() {
15 System.out.println(" Room: " + name + " (" + area + " sq ft)");
16 }
17}
18
19public class House {
20 private String address;
21 private List<Room> rooms; // Composition - strong ownership
22
23 public House(String address) {
24 this.address = address;
25 this.rooms = new ArrayList<>();
26
27 // House creates its own rooms - rooms don't exist outside
28 createDefaultRooms();
29 }
30
31 private void createDefaultRooms() {
32 rooms.add(new Room("Living Room", 400));
33 rooms.add(new Room("Kitchen", 200));
34 rooms.add(new Room("Bedroom", 300));
35 }
36
37 public void addRoom(String name, double area) {
38 rooms.add(new Room(name, area));
39 }
40
41 public void displayHouse() {
42 System.out.println("House at: " + address);
43 for (Room room : rooms) {
44 room.display();
45 }
46 }
47
48 // When house is destroyed, rooms are destroyed too
49}
50
51// Another example: Car and Engine
52public class Engine {
53 private String type;
54 private int horsepower;
55
56 Engine(String type, int horsepower) {
57 this.type = type;
58 this.horsepower = horsepower;
59 }
60
61 public void start() {
62 System.out.println(type + " engine starting...");
63 }
64}
65
66public class Car {
67 private String model;
68 private Engine engine; // Composition - engine is part of car
69
70 public Car(String model, String engineType, int hp) {
71 this.model = model;
72 // Car creates its own engine
73 this.engine = new Engine(engineType, hp);
74 }
75
76 public void start() {
77 System.out.println("Starting " + model);
78 engine.start();
79 }
80
81 // If Car is destroyed, Engine is destroyed too
82}
83
84// Usage
85public class Main {
86 public static void main(String[] args) {
87 House myHouse = new House("123 Main St");
88 myHouse.addRoom("Bathroom", 100);
89 myHouse.displayHouse();
90
91 // When myHouse goes out of scope, all rooms are destroyed
92
93 Car myCar = new Car("Tesla Model S", "Electric", 670);
94 myCar.start();
95
96 // Engine cannot exist without the Car
97 }
98}Rooms are created by House and cannot exist independently. When House is garbage collected, Rooms are too.
Advantages
- ✓
Clear ownership and lifecycle management
- ✓
Encapsulates complexity within the whole
- ✓
Parts are protected from outside interference
- ✓
Natural modeling of real-world containment
Real-World Example
- Human and Heart: Heart cannot exist without the human body
- Car and Engine: Engine is manufactured as part of the car
- Order and OrderItems: Items only make sense within an order
- Document and Paragraphs: Paragraphs belong to one document
Best Practices
- 1.
Use when parts have no meaning without the whole
- 2.
Create parts inside the whole class
- 3.
Don't expose parts directly to outside world
- 4.
Use for value objects and integral components
💡 Interview Tips
Explain it's a strong "has-a" relationship
Parts have dependent lifecycle
Give House-Rooms or Order-OrderItems example
Know UML notation (filled diamond)
Compare with aggregation (weak ownership)
Classic question: composition vs aggregation vs association