▶ 주제 : 복합체 패턴 (Composite pattern).
구조 패턴의 하나.
복합 객체 그룹(전체)과 단일 객체를 동일하게 취급하거나 다룰 수 있게 해주는 방식으로, 재귀적 특성을 띄며 트리(tree) 구조에 가까운 패턴이다.
▶ 구조
복합체 패턴의 구조는 크게 4가지로 분류된다.
▷ 첫 번째 : 컴포넌트 인터페이스(추상클래스도 가능) : Leaf와 Composite를 같은 타입으로 취급하기 위한 인터페이스로써, Leaf와 Composite가 동일하게 가져야 할 함수를 여기에 선언한다.
▷ 두 번째 : 리프 클래스 : 단일 객체를 표현할 클래스로, 그룹의 구성원 역할을 하며 트리구조로 따지면 가장 밑단에 존재하는 나뭇잎 역할을 한다고 보면 된다.
▷ 세 번째 : 컴포지트(복합체) 클래스 : 복합 객체 그룹을 표현할 클래스로, 자식으로 여러개의 Component 타입 멤버를 수용할 수 있도록 구현되어야 한다.
▶ 예시
PPT의 도형이나 그룹을 움직여본다는 상황이라고 했을 때, 아래 예시처럼 표현할 수 있다.
아래 예시는 C#을 기반으로 작성하였다.
public abstract class GraphicComponent
{
    // 기본 X 축
    public int X;
    // 기본 Y 축
    public int Y;
    // 좌표 이동
    public abstract void Move(int x, int y);
}
도형과 그룹을 동일한 그래픽 타입으로 취급하도록 Component 인터페이스 혹은 추상클래스를 정의한다.
이번 예시는 도형을 움직인다는 상황이기 때문에 좌표값을 표현할 멤버변수가 필요하여 추상클래스로 정의하였다.
public class Shape : GraphicComponent
{
    public Shape(int x, int y)
    {
        X = x;
        Y = y;
    }
    public override void Move(int x, int y)
    {
        X += x;
        Y += y;
        Console.WriteLine($"도형 {GetHashCode()}는 x={X}, y={Y} 좌표로 이동하였습니다.");
    }
}
그래픽 컴포넌트를 상속하는 도형 클래스를 정의하였다. Move(int x, int y) 함수를 오버라이딩하여 좌표값이 실제로 반영되게 했다.
using System;
using System.Collections.Generic;
namespace CompositePattern
{
    public class GraphicGroup : GraphicComponent
    {
        private List _graphicComponents;
        public GraphicGroup(int x, int y)
        {
            _graphicComponents = new List();
            X = x;
            Y = y;
        }
        public override void Move(int x, int y)
        {
            X += x;
            Y += y;
            Console.WriteLine($"그룹 {GetHashCode()}는 x={X}, y={Y} 좌표로 이동하였습니다.");
            // 모든 하위 자식 도형들의 좌표를 이동시켜줌.
            // 그룹 안에 또 다른 그룹이 있는 경우 재귀호출이 됨.
            foreach (GraphicComponent g in _graphicComponents)
            {
                g.Move(x, y);
            }
        }
        // 추가
        public void Add(GraphicComponent graphicComponent)
        {
            _graphicComponents.Add(graphicComponent);
        }
        // 삭제
        public void Remove (GraphicComponent graphicComponent)
        {
            _graphicComponents.Remove(graphicComponent);
        }
        // 인덱스에 해당하는 자식을 반환
        public GraphicComponent GetChild(int index)
        {
            return _graphicComponents[index];
        }
    }
}
  그래픽 컴포넌트를 상속하는 그래픽 그룹 클래스를 정의하였다.
그룹의 자식으로 또 다른 그래픽 컴포넌트들을 수용할 수 있고, Move( )가 호출되면 모든 자식의 좌표까지 이동할 수 있도록 재귀호출을 사용하였다.
즉, 그래픽 그룹 안에 도형이나 또 다른 그래픽 그룹을 집어넣어도 일관되게 제어할 수 있다.
// 최상위 그룹 생성
var rootGraphicGroup = new GraphicGroup(0, 0);
// 도형 2개 생성
var shape1 = new Shape(10, 10);
var shape2 = new Shape(5, 20);
// 그룹에 도형 추가
rootGraphicGroup.Add(shape1);
rootGraphicGroup.Add(shape2);
// 서브 그룹을 생성하고 도형 추가
var subGraphicGroup = new GraphicGroup(100, 100);
var shape3 = new Shape(0, 0);
var shape4 = new Shape(50, 75);
subGraphicGroup.Add(shape3);
subGraphicGroup.Add(shape4);
// 최상위 그룹에 서브 그룹을 추가
rootGraphicGroup.Add(subGraphicGroup);
// 그룹째로 이동
rootGraphicGroup.Move(10, 10);
실제 이용 소스코드이다. 그룹에 도형과 또 다른 그룹을 넣어주고 X Y 축 각각 10씩 이동시켰다.
최상위 그룹을 이동시키자 하위 모든 자식들이 이동되었다.
그림으로 설명하자면 위의 소스코드는 이 그림의 트리구조로 구현됬다고 할 수 있다.
▶ 장점
▷ 그룹핑 : 단일 객체와 복합 객체(그룹)를 동일하게 여기기 때문에 묶어서 연산하거나 관리할 때 편하다.
▶  단점 ▷ 디버깅 어려움 : 재귀호출의 특징 상 트리의 Depth가 깊어질 수록 라인 단위의 디버깅에 어려움이 생긴다.
'Programming > 프로그래밍 이론' 카테고리의 다른 글
| [프로그래밍 이론] JWT (Json Web Token) (0) | 2019.04.19 | 
|---|---|
| [디자인 패턴] 팩토리 메소드 패턴 (Factory method pattern) (0) | 2019.03.20 | 
| [디자인 패턴] 빌더 패턴 (Builder pattern) (2) | 2019.03.09 | 
| [디자인 패턴] 추상 팩토리 패턴 (Abstract factory pattern) (0) | 2019.02.14 | 
| [디자인 패턴] 싱글톤 패턴 (Singleton pattern) (1) | 2019.02.13 | 
댓글