컴포지트패턴, 복합패턴 (Composite Pattern) [첫번째]

디자인 패턴 강의를 오랜만에 다시 하는군요.
업무가 바쁜데다가 운동도 하랴 공부도 하랴 요즘은 몸이 2 개였으면 좋겠네요. ^^

오늘은 구조개선을 위한 디자인패턴 중에서 Composite 패턴에 대해 알아보겠습니다.
왜 Bridge 패턴은 건너뛰고 Composite 부터 하냐구요 ?
특별한 이유는 없습니다. 그냥 제가 그렇게 하고 싶어서... ^^
사실은 Bridge 패턴에 대한 정리가 Composite 보다는 시간이 더 걸릴 것 같아서 그렇습니다.
Bridge 패턴에 대해서도 조만간 올리겠습니다. ^^

2. 구조 개선을 위한 디자인 패턴
ㅇ Adapter 패턴
ㅇ Bridge 패턴
Composite 패턴
ㅇ Decorator 패턴
ㅇ Facade 패턴
ㅇ Flyweight 패턴
ㅇ Proxy 패턴

Composite 패턴을 설명하기 위해 MS 파워포인트(Powerpoint)의 그루핑(Grouping)기능을 한번 생각해봅시다.
디자인 패턴을 공부하시는 분 중에서 혹시 파워포인트를 다루지 못하시는 분은 없으시겠죠? ;;;;
파워포인트의 그루핑 기능은 내가 그린 여러개의 도형 및 그림들을 하나로 합치는 기능입니다.
일단 하나로 합쳐놓으면 그 자체로 또 하나의 도형처럼 동작합니다.
하나의 개체가 되어 다른 개체들과 또 그룹을 만들 수 있고 한번에 삭제 또는 이동도 할 수 있습니다.
일단 이 기능은 알고 계신다고 생각하고 진행할테니, 모르시는 분은 파워포인트에서 도형 몇개 그리고 그 도형들을 모두 선택하여 우측 버튼 클릭 후 "그룹"을 선택해보세요.

자, 이제 개발자의 입장에서 이 그룹을 한번 생각해봅시다. (그림 등은 빼고 도형의 그룹이라고 가정하겠습니다.)

  • 그룹은 기본 도형(세모, 네모, 동그라미, 선,...)들이 합쳐져서 만들어진 것이다.
  • 이 그룹은 기본도형들을 이용하여 할 수 있는 기능을 똑같이 수행할 수 있다. (즉, 채우기, 테두리선색 바꾸기, 이동, 복사, 확장, 등등)
  • 그룹이 또 다른 그룹으로 합쳐질 수 있다.
  • 새로운 그룹을 만들 때마다 프로그램을 수정할 필요없이 동적으로 가능한 것이다.

잘 생각해보면 하나하나의 기본 도형도 객체이고, 다수의 도형이 묶인 그룹 도형도 기본 도형과 마찬가지로 객체입니다.
하지만, 그룹 도형 객체는 사용자가 마음대로 만들어낼 수 있다는게 기본 도형 객체와 다릅니다.
Composite 패턴에서는 위의 기본 도형 객체를 기본 객체(Primitive Object)라고 부르고, 그룹 도형 객체는 구성 객체(Composed Object)라고 부릅니다.
처음 기본이 되는 객체이냐, 아니면 그런 기본이 되는 객체를 합쳐 놓은 객체이냐의 차이입니다.

위에서 구성 객체는 또 다른 구성 객체의 요소가 될 수 있다고 했습니다.
그 얘기는 곧 객체의 구성이 Tree 형태로 이루어져 있다는 말과 같습니다.

composed object
/                    |     |
composed object 2      line   circle
/        |
triangle    circle

위처럼 모든 객체들은 다른 구성 객체의 일원이 될 수 있습니다.
그렇다면, 위의 tree 에서 만약 최상위 객체인 composed object 의 일원이 되는 객체들을 하나하나 찾아가려면 무언가 인터페이스가 하나 필요할 것 같지 않나요 ?
전체 구성 객체에서 특정한 하나의 객체를 제외하고 싶을 때는 그 객체를 찾을 수 있는 무언가가 필요한데 composite 패턴에서는 그 함수를 일반적으로 getChild() 함수로 호칭합니다.

아래 그림을 보시죠.

Leaf 는 기본 객체를 의미합니다. Composite 는 위에서 언급한대로 구성 객체를 의미합니다.
그리고, 해당 객체들에 대한 동일한 인터페이스를 제공하기 위해 Component 라는 상위 Class 가 존재합니다.
Abstract Class 라고 불러도 좋습니다.
주의해서 보셔야할 것은 Component Class 의 operation 함수입니다.
해당 함수는 다른 함수와는 다르게 기울임체로 되어 있을 것입니다.
이는 해당 함수가 순수가상함수이어야함을 나타냅니다.
operation 함수는 모든 객체들이 반드시 가져야하는 기능을 말하기 때문에 순수가상함수가 되어 모든 객체들이 이를 구현해야 합니다. 예를 들면, 도형을 화면에 그리는 기능인 Draw() 라는 함수는 모든 객체가 가지고 있어야할 공통함수일 것입니다.
하지만, add, remove, getChild 함수의 경우는 Leaf(기본 객체)는 가질 필요가 없고, 구성객체(Composite Object)들만 가지고 있으면 되는 함수들입니다.

add 는 현재의 구성 객체에 또 다른 객체를 포함시키고자 할 경우 사용하고, remove 함수는 구성 객체의 요소가 되는 특정 객체를 제외하고자 할 경우, 그리고 getChild 함수는 위에서 말씀드린대로 구성 객체 트리를 이루는 요소 들을 탐색할 때 사용하는 함수입니다.
그런데, 왜 add, remove, getChild 는 Composite Class 에만 두면 되지 Component 까지 끌어올렸을까요 ?
이는 add, remove, getChild 함수의 대상이 또한 Composite 객체가 될 수 있기 때문입니다.
즉, 기본 객체나 구성객체들을 add 하고 remove 하여 또 다른 Composite 객체를 만들 수 있는 것이죠.
이러한 행위들이 사용자단에서 동일한 인터페이스로 자유롭게 이루어져야하기 때문에 Abstract Class 인 Component 까지 올라가 있는 것입니다.

이렇게 Composite 패턴은 "기본(Leaf) 객체와 구성(Composite) 객체를 트리 구조로 구성하여 사용자가 해당 객체들을 구분없이 같은 인터페이스로 사용할 수 있게 하기 위한 디자인 패턴"입니다.

다음 시간에는 위의 이론을 바탕으로 sample 소스를 작성해보겠습니다.
위의 구조를 이해하셨다면 아마 소스를 이해하는 것은 껌일 것입니다. ^^

You may also like...

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x