🧩 Composite Pattern
✅ Intent
- Represent objects in a tree structure so that individual objects and groups can be treated uniformly
- Useful when a large
God Object
contains recursive substructures
✅ Motivation
- When a
God Object
contains recursive structures such as UI layouts, document hierarchies, or organizational charts - Enables easy reuse, addition, and removal of components
✅ When to Use
- For classes that handle hierarchical structures such as folder trees, menu hierarchies, or GUI components
- When organizing data structures that recursively contain child elements
✅ Code Example
- TypeScript
- PHP
- Python
// Component(共通インターフェース)
interface OrganizationUnit {
getName(): string;
print(indent?: string): void;
}
// Leaf(個々の要素)
class Employee implements OrganizationUnit {
constructor(private name: string) {}
getName(): string {
return this.name;
}
print(indent: string = ""): void {
console.log(`${indent}- ${this.name}`);
}
}
// Composite(集合)
class Department implements OrganizationUnit {
private members: OrganizationUnit[] = [];
constructor(private name: string) {}
add(unit: OrganizationUnit) {
this.members.push(unit);
}
getName(): string {
return this.name;
}
print(indent: string = ""): void {
console.log(`${indent}+ ${this.name}`);
this.members.forEach((member) => member.print(indent + " "));
}
}
// 利用例
const devTeam = new Department("開発部");
devTeam.add(new Employee("Hiroshi"));
devTeam.add(new Employee("Satoshi"));
const qaTeam = new Department("QA部");
qaTeam.add(new Employee("Yuki"));
const company = new Department("MyCompany");
company.add(devTeam);
company.add(qaTeam);
company.print();
<?php
// Component インターフェース
interface OrganizationUnit {
public function getName(): string;
public function print(string $indent = ""): void;
}
// Leaf
class Employee implements OrganizationUnit {
private string $name;
public function __construct(string $name) {
$this->name = $name;
}
public function getName(): string {
return $this->name;
}
public function print(string $indent = ""): void {
echo "{$indent}- {$this->name}\\n";
}
}
// Composite
class Department implements OrganizationUnit {
private string $name;
private array $members = [];
public function __construct(string $name) {
$this->name = $name;
}
public function add(OrganizationUnit $unit): void {
$this->members[] = $unit;
}
public function getName(): string {
return $this->name;
}
public function print(string $indent = ""): void {
echo "{$indent}+ {$this->name}\\n";
foreach ($this->members as $member) {
$member->print($indent . " ");
}
}
}
// 利用例
$devTeam = new Department("開発部");
$devTeam->add(new Employee("Hiroshi"));
$devTeam->add(new Employee("Satoshi"));
$qaTeam = new Department("QA部");
$qaTeam->add(new Employee("Yuki"));
$company = new Department("MyCompany");
$company->add($devTeam);
$company->add($qaTeam);
$company->print();
from abc import ABC, abstractmethod
# Component
class OrganizationUnit(ABC):
@abstractmethod
def get_name(self) -> str:
pass
@abstractmethod
def print(self, indent: str = ""):
pass
# Leaf
class Employee(OrganizationUnit):
def __init__(self, name: str):
self.name = name
def get_name(self) -> str:
return self.name
def print(self, indent: str = ""):
print(f"{indent}- {self.name}")
# Composite
class Department(OrganizationUnit):
def __init__(self, name: str):
self.name = name
self.members: list[OrganizationUnit] = []
def add(self, unit: OrganizationUnit):
self.members.append(unit)
def get_name(self) -> str:
return self.name
def print(self, indent: str = ""):
print(f"{indent}+ {self.name}")
for member in self.members:
member.print(indent + " ")
# 利用例
dev_team = Department("開発部")
dev_team.add(Employee("Hiroshi"))
dev_team.add(Employee("Satoshi"))
qa_team = Department("QA部")
qa_team.add(Employee("Yuki"))
company = Department("MyCompany")
company.add(dev_team)
company.add(qa_team)
company.print()
✅ Explanation
This code applies the Composite
pattern to provide a unified way to handle hierarchical data structures such as an organizational chart.
The Composite
pattern enables individual objects and composite groups to be treated in the same way, making it ideal for managing tree structures.
- Overview of the Composite Pattern
- Component: Defines a common interface to treat both individual and composite objects uniformly
- In this code, represented by
OrganizationUnit
- In this code, represented by
- Leaf: Represents the end nodes in the tree structure
- Here, represented by
Employee
- Here, represented by
- Composite: Represents a group that can contain child elements
- Here, represented by
Department
- Here, represented by
- Component: Defines a common interface to treat both individual and composite objects uniformly
2. Key Classes and Their Roles
-
OrganizationUnit
- The common interface
- Defines the
getName
andprint
methods used by bothEmployee
andDepartment
-
Employee
- Represents the
Leaf
node - Models an individual employee with a name and implements the
print
method to output its own name
- Represents the
-
Department
- Represents the
Composite
node - Manages a department name and a list of members (
OrganizationUnit
) - Provides an
add
method to add child units, and aprint
method to recursively output itself and its children
- Represents the
3. UML Class Diagram
4. Benefits of the Composite Pattern
- Uniform Operations: Both
Employee
andDepartment
can be treated the same via theOrganizationUnit
interface - Recursive Structure: Allows for the simple representation of deeply nested hierarchies, such as departments within departments
- Extensibility: New element types can be added by implementing the
OrganizationUnit
interface
This design is highly effective when working with hierarchical data structures, and is well-suited for implementations such as organization charts or file systems.