Don't give up!

[Design Pattern] 컴포지트 패턴(Composite Pattern) 본문

개발서적/Head First Design Patterns

[Design Pattern] 컴포지트 패턴(Composite Pattern)

Heang Lee 2021. 12. 22. 23:46
이 글은 에릭 프리먼의 'Head First Design Patterns'를 읽고 TIL(Today I Learned)로써 정리한 내용을 기록하는 글입니다.
자세한 내용은 책을 통해 확인하실 수 있습니다.

알라딘: Head First Design Patterns (aladin.co.kr)

 

Head First Design Patterns

볼 거리가 많고 재미있으면서도, 머리 속에 쏙쏙 들어오는 방식으로 구성된 Head First 시리즈. 패턴의 근간이 되는 객체지향 디자인 원칙, 중요한 패턴, 디자인 적용 방법, 쓰지 말아야 하는 이유

www.aladin.co.kr

컴포지트 패턴 (Composite Pattern)

컴포지트 패턴은 객체들을 트리 구조로 구성하여 부분과 전체를 나타내는 계층 구조로 만드는 디자인 패턴입니다.

Composite 클래스는 Component 클래스를 상속받고, Component 객체를 소유함으로써 개별 객체와 다른 객체들로 구성된 복합 객체를 같은 방법으로 다룰 수 있습니다.

 

컴포지트 패턴에서 Component 클래스는 자식들(Composite)을 관리하는 기능과 Leaf로서의 기능(operation 메소드)을  모두 가지고 있습니다. 이것은 단일 역할 원칙을 위반하지만, Leaf 객체에서는 Composite에서 구현되는 기능이 구현되어 있지 않기 때문에 두 객체를 구별할 수 있어 투명성을 보장할 수 있습니다.

 

//Component 클래스
public abstract class MenuComponent {
    public void add(MenuComponent menuComponent) {
        throw new UnsupportedOperationException();
    }
    
    public void remove(MenuComponent menuComponent) {
        throw new UnsupportedOperationException();
    }
    
    public MenuComponent getChild(int i) {
        throw new UnsupportedOperationException();
    }
    
    public String getName() {
        throw new UnsupportedOperationException();
    }
    
    public String getDescription() {
        throw new UnsupportedOperationException();
    }
    
    public double getPrice() {
        throw new UnsupportedOperationException();
    }
    
    public boolean isVegetarian() {
        throw new UnsupportedOperationException();
    }
    
    public void print() {
        throw new UnsupportedOperationException();
    }
}

//Leaf 클래스
public class MenuItem extends MenuComponent {
    String name;
    String description;
    boolean vegetarian;
    double price;
    
    public MenuItem(String name, String description, boolean vegetarian, double price) {
        this.name = name;
        this.description = description;
        this.vegetarian = vegetarian;
        this.price = price;
    }
    
    public String getName() {
        return name;
    }
    
    public String getDescription() {
        return description;
    }
    
    public double getPrice() {
        return price;
    }
    
    public boolean isVegetarian() {
        return vegetarian;
    }
    
    public void print() {
        System.out.print(" " + getName());
        if (isVegetarian()) {
            System.out.print(" (v) ");
        }
        System.out.println(", " + getPrice());
        System.out.println("  -- " + getDescription());
    }
}

//Composite 클래스
public class Menu extends MenuComponent {
    ArrayList menuComponents = new ArrayList();
    String name;
    String description;
    
    public Menu(String name, String description) {
        this.name = name;
        this.description = description;
    }
    
    public void add(MenuComponent menuComponent) {
        menuComponents.add(menuComponent);
    }
    
    public void remove(MenuComponent menuComponent) {
        menuComponents.remove(menuComponent);
    }
    
    public MenuComponent getChild(int i) {
        return (MenuComponent) menuComponents.get(i);
    }
    
    public String getName() {
        return name;
    }
    
    public String getDescription() {
        return description;
    }
    
    public void print() {
        System.out,print("\n" + getName());
        System.out.println(", " + getDescription());
        Iterator iterator = menuComponents.iterator();
        while (iterator.hasNext()) {
            MenuComponent menuComponent = (MenuComponent) iterator.next();
            menuComponent.print();
        }
    }
}

//Client 클래스
public class Waitress {
    MenuComponent allMenus;
    
    public Waitress(MenuComponent allMenus) {
        this.allMenus = allMenus;
    }
    
    public void printMenu() {
        allMenus.print();
    }
}

public class MenuTestDrive {
    public static void main(String args[]) {
        MenuComponent panckaeHouseMenu = new Menu("팬케이크 하우스 메뉴", "아침 메뉴");
        MenuComponent dinerMenu = new Menu("객체마을 식당 메뉴", "점심 메뉴");
        MenuComponent cafeMenu = new Menu("카페 메뉴", "저녁 메뉴");
        MenuComponent dessertMenu = new Menu("디저트 메뉴", "디저트를 즐겨 보세요!");
        
        MenuComponent allMenus = new Menu("전체 메뉴", "전체 메뉴");
        
        allMenus.add(pancakeHouseMenu);
        allMenus.add(dinerMenu);
        allMenus.add(cafeMenu);
        
        dinerMenu.add(new MenuItem("파스타", "마리나라 소스 스파게티", true, 3.89);
        dinerMenu.add(dessertMenu);
        dessertMenu.add(new MenuIOtem("애플 파이", "바닐라 아이스크림이 얹혀 있는 애플 파이", true, 1.59);
        
        Waitress waitress = new Waitress(allMenus);
        waitress.printMenu();
    }
}