소프트웨어 개발자/디자인패턴

[디자인 패턴] 구조 패턴 - 복합자 패턴

yubi5050 2024. 6. 8. 17:54

구조 (Structure) 패턴

구조 패턴 이란 객체 간의 상호 작용에 대한 구조적 관계를 명확히 정의하여, 코드의 유연성과 재사용성을 높이는 디자인 패턴

 

주요 패턴으론 다음 사항들이 있다.

  • 어댑터 (Adapter) 
  • 데코레이터(Decorator) 
  • 복합자(Composite) <- 이번 글에서 다룰 내용
  • 파셔드(Facade)
  • 플라이웨잇(Flyweight)
  • 프록시(Proxy)
  • 브릿지(Bridge)

 

복합자 (Composite) 패턴 이란

Composite 는 객체를 트리 구조로 구성하여, 트리 전체가 하나의 객체인 것처럼 동작 하게 할 수 있는 구조적 디자인 패턴

1개, 혹은 그 이상의 객체를 연결 지어 명령을 연결에 따라 전파하여, 하나의 객체 처럼 이용하는 것

 

등장 배경

ex) 여러 제품 주문 요청에 대해 각각 따로 포장을 하고 이 모든걸 모아서 최종 하나로 포장을 해야 함 

 

포장 목록 : box(망치, ((폰, 이어폰), 충전기, 주문서))

https://refactoring.guru/images/patterns/diagrams/composite/problem-ko-2x.png

 

예상 코드

  • execute() : 포장을 실행하는 함수
  • 패턴 적용 전 : 망치.execute(), (폰, 이어폰).execute() .... 전체 box.execute()  => 여러번 execute() 가 호출됨
  • 패턴 적용 후 : box.execute() 한 번 호출시 => 알아서 하위 트리들에 전파되도록 ! 

아래 사진과 같이, 트리 구조에 따라 하위로 전파 되는

https://refactoring.guru/images/patterns/content/composite/composite-comic-1-ko-2x.png

 

구조

  1. Leaf와 Composite(=Leaf Group) 클래스를 설계
  2. Leaf, Composite는 모두 execute() box 포장 함수를 가짐
  3. 이 둘(Leaf, Composite)을 컴포넌트 측면에서 동일한 레벨의 객체로 취급
  4. 공통의 Component 인터페이스를 만듬 (Compoent는 execute()라는 추상메소드 가짐)
  5. Leaf Group은 children 리스트 (=즉 Leaf 리스트)를 가지고 이들에 add, remove함
  6. execute() 함수는 기본적으로 내 children들에 대해 확인함
  7. Client가 Component Interface를 구현하여 execute() 함수를 호출
  8. Copmosite의 execute() 실행 -> 자기 children 뒤지면서 Leaf들 execute() 실행

즉 쉽게 말해서 Component (메인 로직 있으며 패턴 객체들을 호출하는 곳)에서 execute() 함수를 수행하고, 그 아래는 Leaf도 있을 수 있고, Composite(Leaf로 구성된) 이 있을 수도 있다. Composite은 하위의 Leaf들에게 전파하고 Leaf는 execute() 실행 후 끝난다.

Component의 execute() 함수 실행시 잘 전파 될 수 있도록, Leaf와 Composite 구성을 잘하면 되는 것

 

https://refactoring.guru/images/patterns/diagrams/composite/structure-ko-2x.png

 

 

장단점

장점

  • 복잡한 트리 구조를 보다 편리하게 작업 가능. (다형성과 재귀)
  • 개방/폐쇄 원칙(OCP) : 트리에 대한 연결만 해두면 새로운 포장품이 추가 될 때, 확장(Open)이 쉬워지고, 수정(폐쇄)도 필요 없음

 

단점

  • 기능이 너무 많이 다른 클래스에 대해 공통 인터페이스를 제공할 때 난해할 수 있음
  • 특정 시나리오에서는 공통 인터페이스를 과도한 일반화가 필요할지도.

 

다른 패턴과의 관계

재귀적 프로그래밍 (execute 함수) 관점

  • 복잡한 복합 트리를 생성할 때 Builder(return 자기자신..) 등을 사용할 수 있음
  • with. 행동 패턴 - 반복자(iterator), 방문자(visitor) 를 사용하여 복합 트리 순회 가능
  • with. 구조 패턴 - Flyweight 활용하여 리프 노드를 Flyweight 로 구현 -> 일부 RAM 절약 가능

 

vs (구조 패턴) Decorator 

  • (공통) 둘 다 재귀적 구성을 사용 (유사한 다이어그램 구조)
  • (공통) 무제한의 개체 수를 구성 할 수 있음.
  • (차이점) Decorator : 하위 구성 요소가 하나만 있고, 해당 래핑된 객체에 추가 책임을 부여 가능
  • (차이점) Composite : Composite는 하위 항목들의 정보를 단순 가지고 있거나, 조합 하는 것