1. 복합 패턴이란 무엇인가요?

복합 패턴은 일반적으로 사용되는 객체 구조 설계 패턴입니다. 객체를 트리 구조로 결합하여 계층적인 "전체-부분" 관계를 나타내어 개별 객체와 개체 조합을 일관된 방법으로 처리할 수 있도록 합니다.

2. 복합 패턴의 특성 및 장점

복합 패턴의 주요 장점은 다음과 같습니다:

  1. 계층적인 복합 객체를 명확하게 정의할 수 있어 새로운 구성 요소를 추가하기 쉽습니다.
  2. 통일된 인터페이스를 제공하여 복합 부분과 개별 객체에 일관된 액세스를 가능하게 하며, 클라이언트가 단일 객체와 복합 객체를 균일하게 사용할 수 있도록 합니다.

3. 복합 패턴의 응용 시나리오

  1. 객체의 전체-부분 계층을 나타내고 싶을 때
  2. 클라이언트가 복합 객체와 개별 객체 간의 차이를 무시하고 복합 구조의 모든 객체를 균일하게 사용하고 싶을 때

4. Golang에서의 복합 패턴 구현

예를 들어, 전자 상거래 애플리케이션을 설계한다고 가정해보겠습니다. 제품 카탈로그는 복합 패턴의 좋은 예시입니다. 카테고리는 다른 카테고리와 제품을 포함할 수 있으며(예: 전자 제품 카테고리에는 휴대폰, 컴퓨터가 있고, 휴대폰에는 아이폰, 삼성폰 등이 포함됩니다).

4.1 UML 클래스 다이어그램

Golang에서의 복합 패턴

4.2 예시 소개

본 예제에서는 Component (명백하게 객체 지향의 인터페이스 특성을 사용하는)를 추상 기본 클래스로 삼고, CompositeLeaf는 둘 다 이 인터페이스를 구현하여 컨테이너 객체와 기본 객체를 나타냅니다.

4.3 구현 단계 1: 추상 구성 요소 클래스 정의

4.3.1 추상 구성 요소 클래스의 인터페이스 정의

//Component: 기본 구성 요소 인터페이스, 그룹 및 개별의 공통성을 정의함
type Component interface {
    Search(string)
}

4.3.2 추상 구성 요소 클래스의 기본 메서드 구현

이 단계에서는 특히 컨테이너 구성 요소 클래스와 리프 구성 요소 클래스에서 구체적으로 구현됩니다.

4.4 구현 단계 2: 리프 구성 요소 클래스 정의

이 구체적인 클래스는 계층 구조의 최하위 카테고리 또는 객체를 나타내며 다음 단계 객체를 가지지 않습니다.

4.4.1 추상 구성 요소 클래스로부터 상속

Go에서는 Struct를 통해 구현된 방법으로 인터페이스 상속이 구현됩니다.

4.4.2 리프 구성 요소 클래스의 특정 메서드 구현

//Product: 리프 노드인 제품을 나타내며, 자식 노드를 가질 수 없습니다
type Product struct {
    Name string
}

//Search: 제품 검색
func (p *Product) Search(keyword string) {
    if strings.Contains(p.Name, keyword) {
        fmt.Printf("제품: '%s'는 키워드 '%s'를 포함합니다\n", p.Name, keyword)
    }
}

4.5 구현 단계 3: 컨테이너 구성 요소 클래스 정의

이 클래스는 자식 객체를 저장하고 관리하며, 일반적으로 add(Component), remove(Component) 등의 자식 객체를 관리하고 구성하는 메서드를 포함합니다.

4.5.1 추상 구성 요소 클래스로부터 상속

Go에서 인터페이스 상속은 Struct를 사용하여 구현됩니다.

4.5.2 컨테이너 구성 요소 클래스의 구체적인 메서드 구현

// Category: 컨테이너 노드인 제품 카테고리를 나타내며, 자식 노드를 가질 수 있습니다
type Category struct {
    Name     string
    Children []Component
}

// Add: 자식 노드 추가
func (c *Category) Add(child Component) {
    c.Children = append(c.Children, child)
}

// Remove: 자식 노드 제거
func (c *Category) Remove(child Component) {
    // 구체적인 구현은 생략합니다
}

// Search: 제품 검색
func (c *Category) Search(keyword string) {
    fmt.Printf("카테고리: %s\n", c.Name)
    for _, composite := range c.Children {
        composite.Search(keyword)
    }
}

4.6 실행 단계 4: 클라이언트 코드 예시

구조체를 인스턴스화하고, 이를 트리 구조로 조립한 다음 트리 구조의 접근 작업을 호출합니다.

func main() {
    root := &Category{Name: "Root"}
    electronics := &Category{Name: "전자제품"}

    phone := &Product{Name: "핸드폰"}
    tv := &Product{Name: "텔레비전"}

    root.Add(electronics)
    electronics.Add(phone)
    electronics.Add(tv)

    root.Search("phone") // 이는 모든 하위 항목에서 검색합니다
}