티스토리 뷰
1. 컴포지트 패턴이란
컴포지트 패턴을 이용하면 객체들을 트리 구조로 구성하여 부분과 전체를 나타내는 계층구조로 만들 수 있다.
이 패턴을 이용하면 클라이언트에서 개별 객체와 다른 객체들로 구성된 복합 객체를 똑같은 방법으로 다룰 수 있다.
구성요소

Composite라는 단어 자체가 복합적인, 합성적인이라는 뜻이다.
어떤 객체 구조가 여러 계층으로 구성되어 있는 복잡한 구조일 때 적용하는 패턴인데, 전형적인 컴포지트 객체는 이런 식으로 생겼다.

Component
- 복합적인 구조를 지닌 객체 (Composite object) 들의 공통 인터페이스
- 모든 객체들이 가지고 있는 default한 기능을 여기서 구현할 수 있다.
- 자녀 컴포넌트에 접근하거나 관리하는 인터페이스를 선언한다.
- (선택사항) 필요하다면 자녀에서 부모 컴포넌트로 재귀적인 접근을 하는 기능도 제공할 수 있다.
Leaf
- leaf 객체는 자녀를 가지지 않는다.
- 복합구조 내에서 가장 기본적인 (primitive) 기능등을 제공한다.
Composite
- 자녀를 가지는 컴포넌트들이 가질 기능들을 여기서 선언한다.
- 자녀 컴포넌트를 가진다.
- 자녀 컴포넌트들과 연관된 함수들을 이 인터페이스에서 구현한다.
Client
- Component 인터페이스를 통해 복합구조 내의 객체들을 조작한다.
2. 동기
장점
- 복잡한 트리 구조를 편리하게 사용할 수 있다.
- 다형성과 재귀를 활용할 수 있다.
- 클라이언트 코드를 변경하지 않고 새로운 아이템 타입을 추가할 수 있다. (Open-closed principle)
단점
- 트리를 만들어야하기 때문에 (공통된 인터페이스를 정의 해야하기 때문에) 지나치게 일반화 해야 하는 경우도 생길 수 있다.
3. 구현
구현 예시
public class Item {
private String name;
private int price;
public Item(String name, int price) {
this.name = name;
this.price = price;
}
public int getPrice() {
return this.price;
}
}
public class Bag {
private List<Item> items = new ArrayList<>();
public void add(Item item) {
items.add(item);
}
public List<Item> getItems() {
return items;
}
}
public class Client {
public static void main(String[] args) {
Item doranBlade = new Item("도란검", 450);
Item healPotion = new Item("체력 물약", 50);
Bag bag = new Bag();
bag.add(doranBlade);
bag.add(healPotion);
Client client = new Client();
client.printPrice(doranBlade);
client.printPrice(bag);
}
private void printPrice(Item item) {
System.out.println(item.getPrice());
}
private void printPrice(Bag bag) {
int sum = bag.getItems().stream().mapToInt(Item::getPrice).sum();
System.out.println(sum);
}
}
위 예시에서는 Item과 Bag가 복합적인 구조를 가진다.
이 구조를 Composite Pattern을 적용하여 Item과 Bag가 Component라는 인터페이스를 공통으로 가지게 만들어 보자.
public interface Component {
int getPrice();
}
public class Item implements Component {
private String name;
private int price;
public Item(String name, int price) {
this.name = name;
this.price = price;
}
@Override
public int getPrice() {
return this.price;
}
}
public class Bag implements Component {
private List<Component> components = new ArrayList<>();
public void add(Component component) {
components.add(component);
}
public List<Component> getComponents() {
return components;
}
@Override
public int getPrice() {
return components.stream().mapToInt(Component::getPrice).sum();
}
}
이렇게 Component의 getPrice()를 오버라이딩하게 되면 Client 코드는 다음과 같이 개선할 수 있다.
public class Client {
public static void main(String[] args) {
Item doranBlade = new Item("도란검", 450);
Item healPotion = new Item("체력 물약", 50);
Bag bag = new Bag();
bag.add(doranBlade);
bag.add(healPotion);
Client client = new Client();
client.printPrice(doranBlade);
client.printPrice(bag);
}
private void printPrice(Component component) {
System.out.println(component.getPrice());
}
}
추가로 만약에 새로운 타입의 객체를 넣는다고 하더라도 클라이언트 코드는 변경없이 그저 Component를 구현하게 하면 된다.
public class Character implements Component {
private Bag bag;
@Override
public int getPrice() {
return bag.getPrice();
}
}
'Computer Science > 디자인 패턴' 카테고리의 다른 글
12.프록시 패턴 (Proxy Pattern) (0) | 2023.11.11 |
---|---|
12. 스테이트 패턴 (State Pattern) (0) | 2023.10.28 |
10. 이터레이터 패턴 (Iterator Pattern) (1) | 2023.10.28 |
9. 템플릿 메소드 패턴 (Template Method Pattern) (0) | 2023.10.16 |
7. 어댑터 패턴 (Adapter Pattern) (0) | 2023.10.08 |
- Total
- Today
- Yesterday
- 2019 Kakao Blind
- Java #JIT #JVM
- spring cloud sleuth
- decorator
- zipkin
- WORA
- 2021
- IOC
- 카카오 코테
- KAKAO 2021
- Java
- 2020 KAKAO
- 코테
- WORE
- nginx 내부
- 카카오코테
- Spring
- jvm
- Kakao Blind
- PatternSyntaxException
- 스프링
- Java #GC #가비지콜렉터 #Garbage Collector
- behavior parameterization
- 프로그래밍 모델
- okhttp3
- 카카오 인턴
- 신규 아이디 추천
- 디자인패턴
- 카카오
- 모던 자바 인 액션
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |