Object Relationships Overview
Objects rarely exist in isolation โ they interact with and depend on each other. Understanding the types of relationships between objects is crucial for building accurate models. There are three main types of relationships: Association, Aggregation, and Composition.
Relationship Strength (strongest to weakest):
Composition โโโถ "owns" and "controls lifecycle"
โ
Aggregation โโโถ "has-a" but independent lifecycle
โ
Association โโโถ "knows about" / "uses"
โ
Dependency โโโถ "temporary use"
Association โ A General Relationship
Association is a broad relationship where two objects are connected but have independent lifecycles. One object "knows about" another and can interact with it, but neither owns or controls the other.
// Association โ Teacher and Student know about each other
class Teacher {
constructor(name) {
this.name = name;
this.students = [];
}
addStudent(student) {
this.students.push(student);
student.teacher = this; // bidirectional association
}
}
class Student {
constructor(name) {
this.name = name;
this.teacher = null;
}
getTeacherName() {
return this.teacher ? this.teacher.name : "No teacher assigned";
}
}
const mrSmith = new Teacher("Mr. Smith");
const alice = new Student("Alice");
mrSmith.addStudent(alice);
console.log(alice.getTeacherName()); // Mr. Smith
// Both objects exist independently
// If alice is deleted, mrSmith still exists and vice versa
Association can be unidirectional (A knows B but not vice versa) or bidirectional (A knows B and B knows A).
Unidirectional:
Order โโโโโโโถ Customer
(Order knows its customer, but Customer doesn't know its orders)
Bidirectional:
Doctor โโโโโโถ Patient
(Both know about each other)
Aggregation โ "Has-A" Without Ownership
Aggregation is a special form of association where one object "has" another, but both can exist independently. The child can be created, used, and destroyed separately from the parent. It's a whole-part relationship without lifecycle dependency.
// Aggregation โ Department has Teachers, but they exist independently
class Department {
constructor(name) {
this.name = name;
this.teachers = []; // aggregation โ "has many" teachers
}
addTeacher(teacher) {
this.teachers.push(teacher);
}
removeTeacher(teacher) {
this.teachers = this.teachers.filter(t => t !== teacher);
}
listTeachers() {
return this.teachers.map(t => t.name).join(", ");
}
}
class Teacher {
constructor(name) {
this.name = name;
}
}
const mathDept = new Department("Mathematics");
const physicsDept = new Department("Physics");
const alice = new Teacher("Alice");
const bob = new Teacher("Bob");
mathDept.addTeacher(alice);
mathDept.addTeacher(bob);
physicsDept.addTeacher(alice); // Alice can belong to multiple depts!
console.log(mathDept.listTeachers()); // Alice, Bob
console.log(physicsDept.listTeachers()); // Alice
// If mathDept is deleted, alice and bob still exist
// If alice moves, mathDept still exists
Real-world examples of aggregation:
โข Library โโhasโโโถ Books (Books exist before and after the library)
โข Team โโhasโโโถ Players (Players can join/leave teams)
โข Playlist โโhasโโโถ Songs (Songs exist independently)
โข Computer โโhasโโโถ Peripherals (USB devices plug in and out)
Composition โ "Has-A" With Ownership
Composition is a strong form of aggregation where the parent owns the child and controls its lifecycle. When the parent is destroyed, its composed children are destroyed too. The child cannot meaningfully exist without the parent.
// Composition โ House owns Rooms, which cannot exist without it
class House {
#address;
#rooms = [];
constructor(address) {
this.#address = address;
}
addRoom(name, area) {
const room = new Room(name, area, this);
this.#rooms.push(room);
return room;
}
getRoomCount() {
return this.#rooms.length;
}
getTotalArea() {
return this.#rooms.reduce((sum, room) => sum + room.area, 0);
}
demolish() {
console.log(`Demolishing house at ${this.#address}`);
this.#rooms.forEach(room => room.destroy());
this.#rooms = [];
}
}
class Room {
#name;
#area;
#house; // back-reference to owning house
constructor(name, area, house) {
this.#name = name;
this.#area = area;
this.#house = house;
}
get area() {
return this.#area;
}
destroy() {
console.log(` Destroying room: ${this.#name}`);
}
describe() {
return `${this.#name} (${this.#area} sq ft) in house`;
}
}
const house = new House("123 Main St");
house.addRoom("Living Room", 300);
house.addRoom("Bedroom", 200);
house.addRoom("Kitchen", 150);
console.log(house.getRoomCount()); // 3
console.log(house.getTotalArea()); // 650
house.demolish();
// Demolishing house at 123 Main St
// Destroying room: Living Room
// Destroying room: Bedroom
// Destroying room: Kitchen
Real-world examples of composition:
โข Car โโownsโโโถ Engine (Engine removed if car is scrapped)
โข Order โโownsโโโถ OrderItem (Items deleted with the order)
โข File โโownsโโโถ Content (Content destroyed when file is deleted)
โข Window โโownsโโโถ Menu (Menu destroyed with window)
Aggregation vs Composition โ Decision Guide
Ask yourself:
1. Can the child exist without the parent?
YES โ Aggregation
NO โ Composition
2. Can the child belong to multiple parents at once?
YES โ Aggregation
NO โ Composition
3. When the parent is destroyed, should the child also be destroyed?
NO โ Aggregation
YES โ Composition
4. Is the relationship permanent or temporary?
Permanent โ Composition
Temporary โ Aggregation or Association
Examples:
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Relationship โ Type โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Team โ Player โ Aggregation (players โ
โ โ can leave/transfer) โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Car โ Engine โ Composition (engine โ
โ โ dies with the car) โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Library โ Book โ Aggregation (books can โ
โ โ be moved/removed) โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Order โ OrderItem โ Composition (items โ
โ โ don't exist without โ
โ โ the order) โ
โโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโ