infinity : 무한한 성장가능성
디자인패턴 - 복합체(Composite) 패턴 본문
복합체 패턴(Composite) 패턴이란? 복합 객체(Composite)와 단일객체(Leaf)를 동일한 컴포넌트로 취급하여
클라이언트에게 동일한 인터페이스를 사용하도록 하는 패턴 즉 복합 객체를 구성하거나 개별적인 객체들을 모두 동일한 방법으로 다룰 수 있게 해주는 패턴
복합체 패턴은 트리 구조를 가진 객체들을 다루는데 유용하다.
복합체 패턴은 개별 객체와 복합 객체의 처리 방법이 다르지 않은 경우, 전체 - 부분 관계로 정의할 수 있다.
복합체 패턴은 객체의 구조가 복잡할 때 유용하며, 객체 간의 결합도를 낮추어 유연성을 높일 수 있다.
새로운 객체 or 복합 객체를 추가해도 클라이언트를 수정할 필요가 없어 유지 보수성이 좋다.
복합체 패턴 구조

Component
Leaf 와 Composite 가 구현해야 하는 인터페이스, Leaf와 Composite는 모두 Component라는 같은 타입으로 다뤄진다.
즉, Leaf 와 Composite를 묶는 공통적인 상위 인터페이스
Composite
복합 객체로서, Leat 역할이나 Composite 역할을 넣어 관리하는 역할
Component 구현체들을 내부 리스트로 관리한다.
add와 remove 메서드를 통해 내부 리스트에 단일 / 복합 객체를 관리한다.
Component 인터페이스의 구현 메서드인 opertaion 은 복합 객체에서 호출되면 재귀하여, 추가 단일 객체를 저장한 하위 복합 객체를 순회하게 된다.
Leaf
단일객체로서, 단순하게 내용물을 표시하는 역할
Component 인터페이스의 구현 메서드인 opertaion 은 단일 객체에서 호출되면 적절한 값만 반환한다.
Client
클라이언트는 Component를 참고해 단일 / 복합객체를 하나의 객체로서 다룬다.
💡 복합체 패턴에서 중요한 것은 Composite와 Leaf 가 동시에 구현하는 operation() 인터페이스 추상 메서드를 정의하고,
Composite 객체의 operation 메서드는 재귀 형태로 구현하는 것
-> 위 부분의 말이 프로그래밍 즉 알고리즘에서의 재귀랑 헷갈려서 처음에는 이해가 잘 안 되었었다.
부가 설명을 달아보자면, 알고리즘에서의 재귀는 함수 자신을 직접 호출해 문제를 작은 문제로 쪼개어 해결하는 방식이고
복합체 패턴에서의 재귀는 트리구조를 순회하는 것에 가깝다.
위의 말이 이해가 되신 분이라면 Composite 패턴의 코드 예로 넘어가도 좋을 거 같습니다. 😊
알고리즘에서의 재귀
대표적인 예: 팩토리얼 계산
int factorial(int n) {
if (n == 1) return 1;
return n * factorial(n - 1);
}
- 함수 자신을 직접 호출합니다.
- 문제를 더 작은 부분으로 나누어 처리합니다.
- 종료 조건이 필수입니다.
복합체 패턴에서의 재귀
@Override
public void operation() {
System.out.println("Composite [" + name + "] 작업 수행");
for (Component child : children) {
// 각 자식의 operation()을 호출 (재귀적 호출)
child.operation();
}
}
- 자기 자신을 직접 호출하지 않고, 자식 객체의 메서드를 호출합니다.
- 트리 구조에서 자식들이 다시 자신과 같은 구조를 가질 때 자연스럽게 재귀적 호출이 발생합니다.
- 동일한 인터페이스를 사용하여 일관성을 유지합니다.
- 종료 조건이 명시적이지 않더라도, 자식이 없는 Leaf에서 자연스럽게 종료됩니다.
💡 개념 정리
- 알고리즘에서의 재귀는 자기 자신을 직접 호출하여 문제를 분할 정복하는 것에 초점이 있습니다.
- 복합체 패턴에서의 재귀는 트리 구조를 따라가면서 모든 구성 요소를 일관되게 처리하는 데 초점이 있습니다.
- 둘 다 재귀적 구조를 가지지만, 의도와 사용 목적이 다르다는 점에서 구별됩니다.
Composite 패턴 코드 예
// 1. Component (공통 인터페이스)
interface Employee {
void showDetails();
}
// 2. Leaf (개별 객체)
class Developer implements Employee {
private String name;
private String position;
public Developer(String name, String position) {
this.name = name;
this.position = position;
}
@Override
public void showDetails() {
System.out.println("Developer: " + name + ", Position: " + position);
}
}
class Designer implements Employee {
private String name;
private String position;
public Designer(String name, String position) {
this.name = name;
this.position = position;
}
@Override
public void showDetails() {
System.out.println("Designer: " + name + ", Position: " + position);
}
}
// 3. Composite (복합 객체)
class Team implements Employee {
private String teamName;
private List<Employee> employees = new ArrayList<>();
public Team(String teamName) {
this.teamName = teamName;
}
public void addEmployee(Employee employee) {
employees.add(employee);
}
public void removeEmployee(Employee employee) {
employees.remove(employee);
}
@Override
public void showDetails() {
System.out.println("Team: " + teamName);
for (Employee employee : employees) {
employee.showDetails();
}
}
}
// 클라이언트 코드
public class CompositePatternDemo {
public static void main(String[] args) {
// Leaf 객체 생성
Employee dev1 = new Developer("Alice", "Backend Developer");
Employee dev2 = new Developer("Bob", "Frontend Developer");
Employee designer = new Designer("Charlie", "UI/UX Designer");
// Composite 객체 생성
Team developmentTeam = new Team("Development Team");
developmentTeam.addEmployee(dev1);
developmentTeam.addEmployee(dev2);
Team designTeam = new Team("Design Team");
designTeam.addEmployee(designer);
// 전체 팀을 하나로 묶는 Composite
Team company = new Team("Tech Company");
company.addEmployee(developmentTeam);
company.addEmployee(designTeam);
// 전체 구성 출력
company.showDetails();
}
}
위의 표에서 공통적으로 사용하는 메서드를 operation으로 정의했는데 위 예 코드에서는 showDetail 이 operation 메서드라고 생각하면 된다.
Composite 객체인 Team 메서드에서 showDetail 메서드를 호출하면 Leaf 객체의 showDetail 메서드를 호출하게 된다.
💡 Composite 패턴의 장점
- 트리 구조를 간단하고 일관성 있게 관리할 수 있다,
- 클라이언트 코드에서 단일 객체와 복합 객체를 동일하게 처리할 수 있다.
- 새로운 구성 요소(Composite 또는 Leaf)를 추가해도 클라이언트 코드 수정이 최소화된다.
참고 블로그
1) https://jangjjolkit.tistory.com/60
'Develop > ❤️ Design pattern' 카테고리의 다른 글
| 디자인 패턴: Factory-method (0) | 2022.03.14 |
|---|---|
| 디자인 패턴 : 싱글톤 패턴, 전략패턴, 프록시 패턴 (0) | 2022.03.14 |