freeParksey
밥세공기
freeParksey
전체 방문자
오늘
어제
  • 분류 전체보기 (150)
    • JAVA (32)
      • 자바스터디 (21)
      • Java in action (6)
      • OOP (1)
      • test (2)
    • 알고리즘 문제 (51)
      • 백준 (49)
    • C (Atmega128) (7)
    • 인공지능 (11)
    • 운영체제 (8)
    • 디자인패턴 (5)
    • 잡다한것 (2)
    • 사용기 (3)
      • 도커 (3)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 백트래킹
  • 백준
  • 동작 파라미터화
  • 운영체제
  • 딥러닝
  • 자바스터디
  • generic
  • 우테코
  • Python
  • dto 변환
  • dto 변환 위치
  • 백트랙킹
  • 프리코스
  • Iterator
  • 그리드
  • 후기
  • Thread 동작
  • java
  • 재귀기초
  • 분류
  • 3주차
  • 스트림
  • 알고리즘
  • 동적계획법
  • 집합과 맵
  • 우아한테크코스
  • Thread #JVM #자바스터디 #
  • Collection
  • 자바
  • 상속

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
freeParksey

밥세공기

[디자인 패턴] - 컴포지트 패턴
디자인패턴

[디자인 패턴] - 컴포지트 패턴

2023. 6. 30. 15:18

컴포지트 패턴이란?

부분-전체 계층 구조로 되어있는 트리구조를 통해 개별 객체와 복합 객체를 똑같은 방법으로 다룰 수 있다.

(출처. 복합체 (refactoring.guru))

 

 

Why?


어떤 문제가 있길래?

  • 다 알고 싶어!
  • 개별 객체 (영수증)과 나머지 상자 내부에서도 어떤 것이 있는지 알고 싶고, 동일한 동작을 원할 때

 

위 그림을 예시로 해보겠습니다.

 

배달받은 상자에는 여러 세부 상자와 영수증이 들어있고, 세부 상자들은 또 다른 상자들로 이루어져 있습니다.

이럴 때 부속품들이 많을 때 각각의 객체와 공통된 상자 박스들도 동일한 결과를 얻고 싶다 가정해 보겠습니다.

 

상황

  • 박스를 받았다!
  • 버즈박스와 충전기 박스, 핸드폰, 모니터가 존재했다.
  • 버즈 박스 : 크래들과 이어버드가 존재
  • 충전기 박스 : 충전기 존재
  • 핸드폰과 모니터 존재

 

여기서 각 부품들은 동일한 기능, 어떤 부품들이 들어 있는지 표시하는 것과, 총 가격이 얼마인지를 나타내는 기능이 필요하다고 생각해보겠습니다.

 

어떻게 해야할까요?

 

What?


박스와 세부 부품들을 동일한 방법으로 다루기 위해 인터페이스 부터 구현해 보겠습니다.

public interface Component {
    void printInfo();
    int getPrice();
}

 

자 끝입니다.

사실 인터페이스가 동일한 기능을 위해 사용한다고 볼 수 있는데 이러한 동작을 책임이 다른 객체에도 동일하게 한다 할 수 있을 거 같습니다.

 

 

How?


자 그럼 완성된 코드를 보여드리겠습니다.

 

[Box]

public class Box implements Component {
    private List<Component> components = new ArrayList<>();
    private Recipe recipe;

    public Box() {
        components.add(new PhonePackage());
        components.add(new Monitor());
        recipe = new Recipe();
    }


    @Override
    public void printInfo() {
        components.stream().forEach(Component::printInfo);
    }

    @Override
    public int getPrice() {
        initrecipe();
        return recipe.getPrice();
    }

    public void initrecipe() {
        this.recipe.initrecipe(components.stream()
                .mapToInt(Component::getPrice)
                .sum());
    }
}

 

[PhonePackage]

public class PhonePackage implements Component {
    private List<Component> components = new ArrayList<>();

    public PhonePackage() {
        components.add(new Buzz());
        components.add(new SamsungCharger());
        components.add(new SamsungPhone());
    }
    @Override
    public void printInfo() {
        components.stream().forEach(Component::printInfo);
    }

    @Override
    public int getPrice() {
        return components.stream()
                .mapToInt(Component::getPrice)
                .sum();
    }
}

 

 

// phone
public class SamsungPhone implements Component {
    @Override
    public void printInfo() {System.out.println("샘송 갤럭쉬 21");}

    @Override
    public int getPrice() {return 100000;}
}

// charger
public class SamsungCharger implements Component {
    @Override
    public void printInfo() {System.out.println("샘송 충전기");}

    @Override
    public int getPrice() {return 5000;}
}

 

 

public class Buzz implements Component{
    private List<Component> components = new ArrayList<>();

    public Buzz() {
        components.add(new Cradle());
        components.add(new Earbud());
    }


    @Override
    public void printInfo() {
        components.stream().forEach(Component::printInfo);
    }

    @Override
    public int getPrice() {
        return components.stream()
                .mapToInt(Component::getPrice)
                .sum();
    }
}

// Earbud
public class Earbud implements Component {
    @Override
    public void printInfo() {System.out.println("버즈 이어버드");}

    @Override
    public int getPrice() {return 10000;}
}
// cradle
public class Cradle implements Component {
    @Override
    public void printInfo() {System.out.println("버즈 크래들");}

    @Override
    public int getPrice() {return 20000;}
}

 

 

이렇게 동일한 인터페이스를 통해 구현하게 된다면 동일한 기능으로 전부 관리할 수 있습니다.

 

 

결과

public static void main(String[] args) {
    Box box = new Box();

    box.printInfo();
    System.out.println(box.getPrice());
}

 

장단점


장점

  • 개방 / 폐쇄 원칙을 지키고 있다. : 기존 코드를 변경하지 않고 확장이 가능
  • 구조가 복잡해도 쉽게 확인 가능하다

 

단점

  • SPR의 원칙이 깨진다. : 하나의 클래스에 두 개의 책임을 가지게 된다.
  • 공통된 인터페이스를 제공하는 만큼, 기능이 유사해야 한다.

 

사용하는 곳


  • 계층적 구조를 간단하게 접근해야 할때

'디자인패턴' 카테고리의 다른 글

[디자인 패턴 - 번외] 플라이웨이트  (0) 2023.07.28
[디자인 패턴] - 반복자 패턴  (2) 2023.06.30
[디자인 패턴] 템플릿 메소드 패턴  (0) 2023.06.28
[디자인 패턴] - 전략 패턴  (0) 2023.06.16
    '디자인패턴' 카테고리의 다른 글
    • [디자인 패턴 - 번외] 플라이웨이트
    • [디자인 패턴] - 반복자 패턴
    • [디자인 패턴] 템플릿 메소드 패턴
    • [디자인 패턴] - 전략 패턴
    freeParksey
    freeParksey
    Github: https://github.com/parksey

    티스토리툴바