Java 디자인 패턴-12.Composite

Composite 패턴

n order might comprise various products, packaged in boxes, which are packaged in bigger boxes and so on. The whole structure looks like an upside down tree.

“하나의 주문은 여러 상품으로 구성될 수 있다. 이 상품들은 여러 개의 다른 박스에 담길 수 있으며 이 박스들 역시 더 큰 박스에 담길 수 있다. 이런 구조는 뒤집힌 트리형태와 같다.” (출처:https://refactoring.guru/design-patterns/composite)

해결하려는 문제

  1. 클라이언트는 트리tree구조의 자료구조에 접근할 때 부모 노드와 leaf노드를 접근하는 api가 틀리다면 소스가 복잡해진다. 부모와 노드를 일관된 방법으로 접근할 수 있다면 클라이언트 구현,변경,테스트,재사용이 쉬워진다.

특징/용도

  1. 트리tree구조의 자료구조에만 적용가능하다.
  2. Composite 객체는 요청을 자식객체들에게 순차적으로 전달forward한다.

클래스 다이어그램

Iterator 패턴(김동석)

소스

  1. Component : 공통 인터페이스로 leaf와 composition이 구현해야 할 메소드가 선언되어 있음
    • Menu.java
      1
      2
      3
      4
      5
      
      package net.dskim.desingpattern.composite;
      
      public interface Menu {
      	public int getPrice();
      }
    • AggregateMenu.java
      1
      2
      3
      4
      5
      
      package net.dskim.desingpattern.composite;
      
      public interface AggregateMenu extends Menu {
      	public void addMenu(Menu menu);
      }
  2. Leaf : 트리의 기본 요소로 하위 요소를 가지고 있지 않는다.
    • Noodle.java
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      
      package net.dskim.desingpattern.composite;
      
      import lombok.extern.slf4j.Slf4j;
      
      @Slf4j
      public class Noodle implements Menu {
      	int price;
      	
      	public Noodle(int price) {
      		this.price = price;
      	}
      
      	@Override
      	public int getPrice() {
      		log.info("price=={}", price);
      		return price;
      	}
      }
    • Rice.java
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      
      package net.dskim.desingpattern.composite;
      
      import lombok.extern.slf4j.Slf4j;
      
      @Slf4j
      public class Rice implements Menu {
      	int price;
      	
      	public Rice(int price) {
      		this.price = price;
      	}
      
      	@Override
      	public int getPrice() {
      		log.info("price=={}", price);
      		return price;
      	}
      }
  3. Composite : Component를 구현implement. leaf의 container역할
    • SetMenu.java
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      
      package net.dskim.desingpattern.composite;
      
      import java.util.ArrayList;
      import java.util.List;
      
      import lombok.extern.slf4j.Slf4j;
      
      @Slf4j
      public class SetMenu implements AggregateMenu {
      	List<Menu> menus ;
      	
      	public SetMenu() {
      		menus = new ArrayList<>();
      	}
      
      	@Override
      	public void addMenu(Menu menu) {
      		menus.add(menu);
      	}
      
      	@Override
      	public int getPrice() {
      		int price = 0;
      		for(Menu menu : menus) {
      			price += menu.getPrice();
      		}
      		log.info("price=={}", price);
      		return price;
      	}
      }

참고