컴퓨터의 파일 시스템에는 디렉터리 라는 것이 있다. 말하기 쉽게 생각하면 폴더라고 생각하면 편하다.
이러한 디렉터리 안에는 파일이 있거나, 다른 하위 디렉터리가 있기도 한다.
마치 "상자 안의 상자" 같은 구조이다. 즉, 재귀적 구조를 가진다.
이때, 디렉터리 엔트리를 차례대로 조사할 때, 그릇과 내용물을 같은 종류로 취급하면 편리할 수 있다.
==> 이때 Composite Pattern을 사용하면 편리하다.
그릇을 내용물과 동일시 하여 재귀적인 구조를 만들기 위한 디자인 패턴
해당 패턴은 구조적 패턴의 마지막을 장식하며 여러가지 패턴이 혼합되어 있다.
느슨한 연결과 비슷하다고 볼 수 있다. 즉, 약한연결/composition/has-a 관계가 비슷한 관계이다.

Leaf의 역할: leaf는 내용물을 표시하는 역할을 하며 내부에 다른 것을 넣을 수 없다.
Composite의 역할: 그릇을 나타내는 역할을 하며 Leaf 역할이나 composite 역할을 넣을 수 있다.
Component의 역할: Leaf 역할과 Composite 역할을 동일시하기 위한 역할을 하며, component는 leaf 역할과 composite 역할에 공통적인 상위 클래스로 실현한다.
Component : 큰 바구니 = API
Composite : 바구니 안에 있는 그릇 = 연결 및 담을 수 있도록 함.
Leaf : 음식물 = 일반적인 객체 하나로써, 더 이상 쪼개지지 않는다.
객체 그룹과 객체의 single instance가 같은 타입으로 취급되는 패턴
Composite pattern을 통해 객체를 트리 구조로 구성할 수 있다.

하나의 객체와 그 객체가 들어있는 그룹을 같은 타입으로 취급한다.
그룹은 리스트로 이루어져 있으며 안에 객체가 들어간다.
같은 타입으로 취급한다는 말은 둘이 같은 interface를 가지고 있다는 뜻이다.
여기서는 Base Interface Component, 상속받은 객체를 Leaf, 이를 상속받은 그룹을 Composite이라고 한다.
Component를 상속받은 leaf와 composite은 Component와 같은 함수를 가지고 있어야 한다.

강이지와 고양이를 묶는 그룹을 관련 패턴으로 제작해보자.
class Animal:
def speak(self):
pass
class Cat(Animal):
def speak(self):
print("meow")
class Dog(Animal):
def speak(self):
print("bark")
class AnimalGroup(Animal):
def __init__(self):
self.animals = []
def add(self, animal: Animal):
self.animals.append(animal)
def speak(self):
print("group speaking: ")
for animal in self.animals:
animal.speak()
# cat_group 생성 및 Cat 객체 추가
cat_group = AnimalGroup()
cat_group.add(Cat())
cat_group.add(Cat())
cat_group.add(Cat())
# dog_group 생성 및 Dog 객체 추가
dog_group = AnimalGroup()
dog_group.add(Dog())
dog_group.add(Dog())
dog_group.add(Dog())
# zoo 생성 및 cat_group, dog_group 추가
zoo = AnimalGroup()
zoo.add(cat_group)
zoo.add(dog_group)
# zoo의 speak() 메서드 호출
zoo.speak()