Computer Science

Composite Pattern | 컴포짓 패턴

연_우리 2022. 8. 15. 00:55
반응형

목차

     

     

     

    어떤 상황에서 쓰일까?

    게임 캐릭터는 가방에 도란검과 체력물략을 가지고있다

    보통 아이템에 마우스를 올리면 가격이 출력되는데, 

    도란검 가격을 출력하는것이나, 가방의 모든 아이템의 가격을 출력하는 것이나

    게임 캐릭터 입장에선 동일하게 가격을 출력하는 것이다.

     

    가방은 아이템을 담을 수 있는 것이니 가방에.. 가격 출력 메서드가 있어야할까??

    아니면 아이템에 가격출력 메서드를 추가해서

    가방의 모든 아이템 가격을 출력할 땐 아이템 전체를 순회해야할까???

     

     

    컴포짓 패턴이란?

    그룹 전체와 개별 객체를 동일하게 처리할 수 있는 패턴이다.

    클라이언트 입장에서 전체나 부분이나 동일한 컴포넌트로 인식할 수 있어야한다.

    다시말해 일괄적인 관리가 가능하게끔 된다!

     

     

    * 트리구조이어야 하는 제약사항이 있다!

     

    장점

    - 복잡한 트리 구조를 편리하게 사용할 수 있다

    - 다형성과 재귀 활용 가능하다

    - 새로운 엘리먼트 타입이 추가되어도 클라이언트 코드가 변경되지 않는다 (printPrice(Component component))

     

    단점

    - 공통된 인터페이스를 정의해야하기 때문에 지나치게 일반화해야하는 경우도 생길 수 있다

    (지금은 아이템과 가방이니 연관성을 찾을 수 있지만.. 아예 다른 연관관계를 가진경우는 오히려 컴포짓패턴이 발목을 잡는다!)

     

     

     

     

    구현코드

    기존코드

    public class Client {
    
        public static void main(String[] args) {
            Item doranBlade = new Item("도란검", 450);
            Item healPotion = new Item("체력 물약", 50);
    
            Bag bag = new Bag();
            bag.add(doranBlade);
            bag.add(healPotion);
    
            Client client = new Client();
            client.printPrice(doranBlade);
            client.printPrice(bag);
        }
    
        private void printPrice(Item item) {
            System.out.println(item.getPrice());
        }
    
        private void printPrice(Bag bag) {
            int sum = bag.getItems().stream().mapToInt(Item::getPrice).sum();
            System.out.println(sum);
        }
    
    }

    아이템 유형이 아이템인지, 가방인지에 따라 메서드를 다르게 구현해주어야한다

    public class Bag {
    
        private List<Item> items = new ArrayList<>();
    
        public void add(Item item) {
            items.add(item);
        }
    
        public List<Item> getItems() {
            return items;
        }
    }

     

     

     

    변경코드

    public interface Component {
        int getPrice();
    }
    public class Bag implements Component {
    
        private List<🔥Component> components = new ArrayList<>();
    
        public void add(🔥Component component) {
            components.add(component);
        }
    
        public List<🔥Component> getComponents() {
            return components;
        }
    
        @Override
        public int getPrice() {
            return components.stream().mapToInt(Component::getPrice).sum();
        }
    }
    public class Client {
    
        public static void main(String[] args) {
            Item doranBlade = new Item("도란검", 450);
            Item healPotion = new Item("체력 물약", 50);
    
            Bag bag = new Bag();
            bag.add(doranBlade);
            bag.add(healPotion);
    
            Client client = new Client();
            client.printPrice(doranBlade);
            client.printPrice(bag);
        }
    
        private void printPrice(Component component) {
            System.out.println(component.getPrice());
        }
    
    }

    가방과 아이템 모두 Component를 구현하고 있어 동일하게 취급할 수 있게되었다!

    가방과 아이템에 따라 달라지던 메서드를 Component하나로 줄일 수 있게되었다

    반응형
    • 네이버 블러그 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 구글 플러스 공유하기
    • 카카오톡 공유하기