Composite Pattern (디자인 패턴 11장)

컴포지트 패턴 정의

객체들을 트리 구조로 구성하여 부분과 전체를 나타내는 계층구조로 만들 수 있습니다.
이 패턴을 이용하면 클라이언트에서 개별 객체와 다른 객체들로 구성된 복합 객체를 똑같은 방법으로 다룰 수 있다.

컴포지트 패턴 언제 사용할까!?

식당에 메뉴가 있는데 아침 메뉴 점심 메뉴 저녁메뉴가 있을 수 있고 또 다른 디저트 메뉴 혹은 디저트 메뉴 안에서도 또 다른 메뉴로 나뉘어 질 수 있다.
이런 식으로 계층 구조로 생각 해야 하는 경우 사용하면 유용하다.

아래의 코드를 보자.


class CompositePattern {
    @Test
    fun test() {
        val allMenus = Menu("전체메뉴")

        val breakfastMenu = Menu("아침메뉴").apply {
            menuComponents.apply {
                add(MenuItem("토스트", 3000))
                add(MenuItem("삼겹살", 10000))
                add(MenuItem("김밥", 2500))
            }
        }

        val lunchMenu = Menu("점심메뉴").apply {
            menuComponents.apply {
                add(MenuItem("ㅄㅎㄱ", 10000))
                add(MenuItem("ㅍㅇㅈ", 3500))
            }
        }

        allMenus.menuComponents.apply {
            add(breakfastMenu)
            add(lunchMenu)
        }

        allMenus.print()

    }

    //Component
    abstract class MenuComponent {
        abstract fun print()
    }

    //Leaf
    class MenuItem(private val name: String, private val price: Int) : MenuComponent() {
        override fun print() {
            println("name : $name , price : $price")
        }
    }

    //Composite
    class Menu(private val name: String) : MenuComponent() {
        val menuComponents = arrayListOf<MenuComponent>()

        override fun print() {
            println("name : $name")
            val iterator = menuComponents.iterator()
            while (iterator.hasNext()) {
                val menuComponent = iterator.next()
                menuComponent.print()
            }
        }
    }
}

Leaf 에서는 더 이상 메뉴를 추가,제거 할 수 없다.
Composite 에서만 가능

아래는 테스트 결과이다.

[사진 자료 출처] (https://ko.wikipedia.org/wiki/%EC%BB%B4%ED%8F%AC%EC%A7%80%ED%8A%B8_%ED%8C%A8%ED%84%B4#:~:text=%EC%BB%B4%ED%8F%AC%EC%A7%80%ED%8A%B8%20%ED%8C%A8%ED%84%B4(Composite%20pattern)%EC%9D%B4%EB%9E%80,%EB%8F%99%EC%9D%BC%ED%95%98%EA%B2%8C%20%EB%8B%A4%EB%A3%A8%EB%8F%84%EB%A1%9D%20%ED%95%9C%EB%8B%A4.)