▶ 주제 : 복합체 패턴 (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 |
댓글