Association
A general relationship: one object knows about or collaborates with another, but ownership is not implied.
Many class diagrams become confusing because they label relationships without explaining the design implication. Association, aggregation, and composition are not just UML vocabulary. They help you reason about how objects depend on each other, who owns what, and whether one object’s lifetime is tied to another.
In an e-commerce domain, an Order is composed of OrderLines. A Customer may be associated with Orders over time. A Shipment might aggregate packaged items but still reference external warehouse data. Those distinctions guide lifecycle, persistence, and invariants.
Association is the broadest relationship. A Customer and an Order are associated because the order belongs to the customer contextually, but the customer object and order object can exist independently in the system.
Aggregation is often subtle in code because Java references alone do not enforce lifecycle. It is mostly a modelling distinction that helps express “contains, but does not fully own.”
Composition is often the most useful for OOAD because it tells you where invariants belong. If an Order is composed of OrderLines, then the order should often control how those lines are created, validated, and changed.
A general relationship: one object knows about or collaborates with another, but ownership is not implied.
A whole-part relationship where the part can still exist independently of the whole.
A strong whole-part relationship where the part belongs to the whole and shares its lifecycle more tightly.
package org.javaomnibus.ecommerce.foundations;
import java.util.ArrayList;
import java.util.List;
public final class Order {
private final String orderId;
private final Customer customer; // association
private final List lines = new ArrayList<>(); // composition
public Order(String orderId, Customer customer) {
this.orderId = orderId;
this.customer = customer;
}
public void addLine(String sku, int quantity) {
lines.add(new OrderLine(sku, quantity));
}
public List lines() {
return List.copyOf(lines);
}
}
record Customer(String customerId, String name) {}
record OrderLine(String sku, int quantity) {}
These relationships can be over-formalized. In Java, the code alone will not enforce all lifecycle semantics, so the model and team conventions must support the intent.