그룹 전체와 개별 객체를 동일하게 처리할 수 있는 패턴
클라이언트 입장에서는 '전체'나 '부분'이나 모두 동일한 컴포넌트로 인식할 수 있는 계층 구조를 만든다
(Part-Whole Hierarchy)
public interface Component {
int getPrice();
}
계층 구조에 사용할 공통 Component 인터페이스를 정의한다
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 final 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();
}
}
public class Character implements Component {
private Bag bag;
@Override
public int getPrice() {
return bag.getPrice();
}
}
계층 구조에 사용할 Component를 상속받는 클래스들을 만든다. 이때, 클래스들 내부에서 참조하는 Component들은 리프 클래스를 사용해선 안된다. 반드시 최상위 계층인 Component 인터페이스를 사용하여 Component를 상속받는 어떤 클래스가 들어오더라도 대응하도록 해야한다.
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 타입으로 합수를 사용하면 된다
- 장점
- 복잡한 트리 구조를 편리하게 사용할 수 있다
- 다형성과 재귀를 활용할 수 있다
- 클라이언트 코드를 변경하지 않고 새로운 엘리먼트 타입을 추가할 수 있다
- 단점
- 트리를 만들어야 하기 때문에 (공통된 인터페이스를 정의해야 하기 때문에) 지나치게 일반화 해야 하는 경우도 생길 수 있다
'java' 카테고리의 다른 글
Design Patterns - Facade (0) | 2021.12.10 |
---|---|
Design Patterns - Decorator (0) | 2021.12.04 |
Design Patterns - Bridge (0) | 2021.11.28 |
Design Patterns - Adapter (0) | 2021.11.24 |
Design Patterns - Prototype (0) | 2021.11.22 |
댓글