Fall in IT.

컴포지트 패턴(Composite Pattern) 간단히 살펴보기 본문

기타

컴포지트 패턴(Composite Pattern) 간단히 살펴보기

D.Y 2023. 4. 30. 14:57

Composite Pattern

컴포짓 패턴

그룹 전체와 개별 객체를 동일하게 처리할 수 있는 패턴

  • 클라이언트 입장에서 ‘전체’나 ‘부분’이나 모두 동일한 컴포넌트로 인식할 수 있는 계층을 만든다. (Part-Whole Hierarchy)

 

 

예를들어, 가방에 물건(아이템)이 5가지 존재한다고 생각해보자.

  • 립밤
  • 향수
  • 노트북
  • 안경

물건들은 각각 쓰임새는 다르지만, 그에 해당하는 이름과 가격이 정해져있다.

이때 우리는 물건의 각각의 가격과 가방안에 든 모든 물건들의 가격을 알고 싶다고 할 경우에 컴포짓 패턴을 유용하게 사용할 수 있다.

가방 → 컴포지트를 나타내고 컴포지트는 안에 컴포넌트들을 갖고 있다.

컴포넌트 → 물, 향수 등이 해당되고 컴포지트에 기능 실행을 요청하면 컴포지트는 포함하고 있는 컴포넌트들의 기능 실행을 통해 값을 계산한다.

 

 

아래 예제코드는 Go를 사용하여 작성하였다. (전체 코드는 여기에 있다.)

 

main 코드 작성

func main() {
	var (
		water   src.Item
		perfume src.Item
		glasses src.Item
		laptop  src.Item
	)

	water = src.NewWater("삼다수", 2000)
	perfume = src.NewPerfume("재즈클럽", 140000)
	glasses = src.NewGlasses("젠틀몬스터", 249000)
	laptop = src.NewLaptop("맥북 프로", 3990000)

	// 가방에 물건 담기
	bag := src.NewBag("샘소나이트", 129000)
	bag.AddItem(water)
	bag.AddItem(perfume)
	bag.AddItem(glasses)
	bag.AddItem(laptop)

	// 아이템 가격 출력하기
	fmt.Println(water.Name() + ": " + fmt.Sprint(water.Price()))
	fmt.Println(perfume.Name() + ": " + fmt.Sprint(perfume.Price()))
	fmt.Println(glasses.Name() + ": " + fmt.Sprint(glasses.Price()))
	fmt.Println(laptop.Name() + ": " + fmt.Sprint(laptop.Price()))
	fmt.Println(bag.Name() + ": " + fmt.Sprint(bag.Price()))

	// 가방에 들은 모든 물건의 가격 출력하기
	fmt.Println("총 가격: " + fmt.Sprint(bag.ItemTotalPrice()))
}

컴포넌트 인터페이스로 Item 인터페이스 정의

type Item interface {
	Name() string
	Price() int
}

물, 향수, 노트북 객체 생성

// 물 
type Water struct {
	name  string
	price int
}

func NewWater(name string, price int) *Water {
	return &Water{
		name:  name,
		price: price,
	}
}

func (p Water) Name() string {
	return p.name
}

func (p Water) Price() int {
	return p.price
}

// 향수
type Perfume struct {
	name  string
	price int
}

func NewPerfume(name string, price int) *Perfume {
	return &Perfume{
		name:  name,
		price: price,
	}
}

func (p Perfume) Name() string {
	return p.name
}

func (p Perfume) Price() int {
	return p.price
}

// 노트북 
type Laptop struct {
	name  string
	price int
}

func NewLaptop(name string, price int) *Laptop {
	return &Laptop{
		name:  name,
		price: price,
	}
}

func (l Laptop) Name() string {
	return l.name
}

func (l Laptop) Price() int {
	return l.price
}

마지막으로 컴포지트에 해당하는 가방 생성

package src

type Bag struct {
	name  string
	price int
	items []Item
}

func NewBag(name string, price int) *Bag {
	return &Bag{
		name:  name,
		price: price,
		items: nil,
	}
}

func (b Bag) Name() string {
	return b.name
}

func (b Bag) Price() int {
	return b.price
}

func (b *Bag) AddItem(item Item) {
	b.items = append(b.items, item)
}

func (b Bag) ItemTotalPrice() int {
	var itemTotalPrice int

	// 컴포넌트 실행
	for _, v := range b.items {
		itemTotalPrice += v.Price()
	}

	return itemTotalPrice
}

 

모두 즐거운 코딩하세요~

 

참조

- [도서] 개발자가 반드시 정복해야할 객체지향과 디자인 패턴

- [인프런] 코딩으로 학습하는 GoF의 디자인패턴

Comments