Composition
Strong ownership - parts cannot exist without the whole.
Composition is a “has-a” relationship where one class contains another, and the contained class cannot exist independently. It represents a strong ownership relationship with tied lifecycles.
What is Composition?
Section titled “What is Composition?”Composition represents:
- “Has-a” relationship (strong ownership)
- Parts cannot exist independently of the whole
- Parts belong to only one whole
- Lifecycle dependency - parts are destroyed when whole is destroyed
Key Characteristics
Section titled “Key Characteristics”- Strong ownership - Container owns the parts
- Dependent lifecycle - Parts cannot exist without container
- Single ownership - Parts belong to only one container
- Filled diamond in UML diagrams
Basic Composition Example
Section titled “Basic Composition Example”class Car: def __init__(self, brand: str, model: str): self.brand = brand self.model = model # Composition - Engine cannot exist without Car self.engine = Engine() # Created when Car is created self.wheels = [Wheel() for _ in range(4)] # Created with Car
def start(self): return self.engine.start()
class Engine: def __init__(self): self.running = False
def start(self): self.running = True return "Engine started"
class Wheel: def __init__(self): self.size = 16
# Engine and Wheels are created and destroyed with Carcar = Car("Toyota", "Camry")print(car.start()) # "Engine started"# When car is deleted, engine and wheels are also gonepublic class Car { private String brand; private String model; private Engine engine; // Composition - Engine cannot exist without Car private java.util.List<Wheel> wheels; // Composition - Wheels created with Car
public Car(String brand, String model) { this.brand = brand; this.model = model; // Created when Car is created this.engine = new Engine(); this.wheels = new java.util.ArrayList<>(); for (int i = 0; i < 4; i++) { wheels.add(new Wheel()); } }
public String start() { return engine.start(); }}
public class Engine { private boolean running;
public Engine() { this.running = false; }
public String start() { this.running = true; return "Engine started"; }}
public class Wheel { private int size;
public Wheel() { this.size = 16; }}
// Usagepublic class Main { public static void main(String[] args) { // Engine and Wheels are created and destroyed with Car Car car = new Car("Toyota", "Camry"); System.out.println(car.start()); // "Engine started" // When car is garbage collected, engine and wheels are also gone }}Visual Representation
Section titled “Visual Representation”Real-World Example: Order System
Section titled “Real-World Example: Order System”class Order: def __init__(self, order_id: str, customer_name: str): self.order_id = order_id self.customer_name = customer_name self.items = [] # Composition - OrderItems belong to Order self.shipping_address = Address("", "", "", "") # Composition
def add_item(self, product_name: str, quantity: int, price: float): item = OrderItem(product_name, quantity, price) # Created by Order self.items.append(item)
def set_shipping_address(self, street, city, state, zip_code): self.shipping_address = Address(street, city, state, zip_code)
def get_total(self): return sum(item.get_subtotal() for item in self.items)
class OrderItem: def __init__(self, product_name: str, quantity: int, price: float): self.product_name = product_name self.quantity = quantity self.price = price
def get_subtotal(self): return self.quantity * self.price
class Address: def __init__(self, street: str, city: str, state: str, zip_code: str): self.street = street self.city = city self.state = state self.zip_code = zip_code
# OrderItems and Address are created with Orderorder = Order("ORD-001", "Alice")order.add_item("Laptop", 1, 999.99)order.add_item("Mouse", 2, 29.99)order.set_shipping_address("123 Main St", "SF", "CA", "94102")
print(f"Order total: ${order.get_total():.2f}") # $1059.97# When order is deleted, items and address are also gonepublic class Order { private String orderId; private String customerName; private java.util.List<OrderItem> items; // Composition - OrderItems belong to Order private Address shippingAddress; // Composition
public Order(String orderId, String customerName) { this.orderId = orderId; this.customerName = customerName; this.items = new java.util.ArrayList<>(); this.shippingAddress = new Address("", "", "", ""); }
public void addItem(String productName, int quantity, double price) { OrderItem item = new OrderItem(productName, quantity, price); // Created by Order items.add(item); }
public void setShippingAddress(String street, String city, String state, String zipCode) { this.shippingAddress = new Address(street, city, state, zipCode); }
public double getTotal() { return items.stream() .mapToDouble(OrderItem::getSubtotal) .sum(); }}
public class OrderItem { private String productName; private int quantity; private double price;
public OrderItem(String productName, int quantity, double price) { this.productName = productName; this.quantity = quantity; this.price = price; }
public double getSubtotal() { return quantity * price; }}
public class Address { private String street; private String city; private String state; private String zipCode;
public Address(String street, String city, String state, String zipCode) { this.street = street; this.city = city; this.state = state; this.zipCode = zipCode; }}
// Usagepublic class Main { public static void main(String[] args) { // OrderItems and Address are created with Order Order order = new Order("ORD-001", "Alice"); order.addItem("Laptop", 1, 999.99); order.addItem("Mouse", 2, 29.99); order.setShippingAddress("123 Main St", "SF", "CA", "94102");
System.out.printf("Order total: $%.2f%n", order.getTotal()); // $1059.97 // When order is garbage collected, items and address are also gone }}Composition vs Aggregation
Section titled “Composition vs Aggregation”| Feature | Composition | Aggregation |
|---|---|---|
| Ownership | Strong | Weak |
| Lifecycle | Dependent | Independent |
| Multi-ownership | No | Yes |
| UML Symbol | Filled diamond | Hollow diamond |
| Example | Car → Engine | University → Students |
Key Takeaways
Section titled “Key Takeaways”When to Use Composition
Section titled “When to Use Composition”Use Composition when:
- Parts cannot exist without the whole
- Parts belong to only one whole
- Lifecycle is tied together
- Relationship is essential and permanent
- Parts are created by the whole
Examples:
- Car → Engine (engine doesn’t exist without car)
- Order → OrderItems (items don’t exist without order)
- House → Room (rooms don’t exist without house)
- Document → Paragraph (paragraphs don’t exist without document)
- Computer → CPU (CPU doesn’t exist without computer)