복합 패턴(Composite Pattern) ; 추상화
객체들을 트리구조로 구성하여, 부분과 전체를 나타내는 계층구조로 만들 수 있다.
이 패턴을 이용하면 클라이언트에서 개별 객체와 다른 객체들로 구성된 복합객체(Composite)를 똑같은 방법으로 다룰 수 있다.
클라이언트는 Component 라는 복합객체 인터페이스에 의존하여 복합노드를 포함한 하위 모든 객체에 접근하거나 조작 가능하다.
Tree와 Composite Pattern 의 구성요소 비교
Tree의 구성요소
- 노드(Node) : 자식이 있는 원소
- 잎(Leaf) : 자식이 없는 원소
Composite Pattern 의 구성요소
- Composite : 자식이 있는 객체
- Leaf : 자식이 없는 객체
책에서 나오는 예제 - Category 가 다른 Menu 구성하기
클라이언트(웨이트리스)가 접근할 MenuComponent 를 구성하는 예제에 대해 설명하고 있다.
MenuComponent
최상위 Composite, 클라이언트가 접근할 interface
1 | public interface MenuComponent { |
MenuItem
Leaf에 해당하는 객체, MenuComponent 로 부터 add, remove 는 구현하지 않는다.
–> leaf 에서 add, remove 메소드를 호출하면 UnsupportedOperationException
이 발생한다.
1 | public class MenuItem implements MenuComponent { |
Menu
Composite 객체, 또 다른 Components 를 멤버로 갖고 있다. 또한 leaf의 역할도 수행하기 위해 leaf 의 구성요소도 멤버로 갖고 있다.
1 | public class Menu implements MenuComponent { |
결론
우리가 객체를 설계할 때 그 구조가 트리구조를 가지고 있을 때, 컴포지트 패턴을 사용하면 이점이 많다.
하지만, 패턴은 추상화를 통해 과도하게 일반화 하고 있는 것은 아닌가 질문을 던져야 할 때가 있다.
컴포지트 패턴의 가장 큰 이점은 ‘클라이언트가 개별 객체와 컬렉션 객체를 동일한 인터페이스로 제어 가능’ 하다는 점을 충분히 인지해야 한다.
생각해보자
컴포지트 패턴에서는 그 활용도가 높을 것이라 기대하진 않았다.
다만, ‘Tree 자료구조를 쓰면 되지 뭐하러 이렇게 귀찮게 쓰지?’ 라는 다소 위험한 생각을 하게 되었다.
Tree vs Composite : 데이터 vs 객체
만약 디렉토리 구조를 시스템으로 구현한다고 가정해보자, 물론 계층구조라는 점과 node, leaf 가 명확히 구분된다는 점에서
‘Tree’ 라는 자료구조가 먼저 떠오르게 된다. (그리고 계층구조를 그리다 보면 필연적으로 Tree 구조로 그리게 되어 있다.)
Tree 는 기본적으로 어떤 데이터를 다루기 위한 자료구조이다. 따라서 아래와 같은 장 단점이 존재할 것이다.
Tree 장점
- Tree 에 익숙한 개발자라면, 구현 난이도나 활용도가 높다
- 순회 탐색에 특화된 자료구조이기 때문에 요소 탐색의 방법이 많다(전위, 중위, 후위 …)
Tree 단점
- Tree 라는 자료구조의 기능으로만 제한된다.
- 실제 Tree 를 구현해보면 V, T 의 재귀형태로 구현해야 한다.
익숙하지 않다면, 구현하는데 꽤나 어려움이 있다.
데이터를 다루기 위함인지, 객체를 구성하기 위함인 지 구분해야 한다.
컴포지트 패턴은 객체를 다루기 위한 기술이다. 목적에서도 알 수 있듯이 ‘클라이언트가 동일한 인터페이스로 개별객체와 컬렉션을 제어하기 위함’에 있음을 알아야 한다.
물론 구현하는 기술이나 방법은 Tree와 매우 흡사하지만, 객체의 세계에서는 전혀 다르다는 것을 알아야 할 것 같다.
책에서는 방법론적인 측면에서 Tree와 재귀, 컴포지트 패턴이 매우 유사하다고만 나와 있어서 조금 아쉬웠다.