JUINTINATION

컴퍼지트(Composite) 패턴 본문

JAVA객체지향디자인패턴

컴퍼지트(Composite) 패턴

DEOKJAE KWON 2023. 7. 17. 23:47
반응형

컴퍼지트 패턴이란?

부분-전체의 관계를 갖는 객체들 사이의 관계를 정의하여 클라이언트가 전체와 부분을 구분하지 않고 동일한 인터페이스를 사용할 수 있게 만드는 패턴이다.

다음과 같이 컴퓨터를 모델링했다고 하자.

컴퓨터는 다음과 같이 키보드(Keyboard 클래스), 본체(Body 클래스), 그리고 모니터(Monitor) 클래스로 이루어져있다.

class Keyboard {
    private int price;
    private int power;
    public Keyboard(int price, int power) {
        this.price = price;
        this.power = power;
    }
    public int getPrice() {
        return price;
    }
    public int getPower() {
        return power;
    }
}

class Body {
    private int price;
    private int power;
    public Body(int price, int power) {
        this.price = price;
        this.power = power;
    }
    public int getPrice() {
        return price;
    }
    public int getPower() {
        return power;
    }
}

class Monitor {
    private int price;
    private int power;
    public Monitor(int price, int power) {
        this.price = price;
        this.power = power;
    }
    public int getPrice() {
        return price;
    }
    public int getPower() {
        return power;
    }
}

class Computer {
    private Keyboard keyboard;
    private Body body;
    private Monitor monitor;
    public void addKeyboard(Keyboard keyboard) {
        this.keyboard = keyboard;
    }
    public void addBody(Body body) {
        this.body = body;
    }
    public void addMonitor(Monitor monitor) {
        this.monitor = monitor;
    }
    public int getPrice() {
        return keyboard.getPrice() + body.getPrice() + monitor.getPrice();
    }
    public int getPower() {
        return keyboard.getPower() + body.getPower() + monitor.getPower();
    }
}
  • 위 코드의 문제점
    • 키보드, 본체, 모니터 이외에 스피커 등 다른 부품이 추가되면 기존의 Computer 클래스 코드를 수정해야 한다.
      • 유지 보수의 어려움
      • OCP 위반

위의 문제를 해결하기 위해 구체적인 부품들을 일반화한 클래스를 정의하고 이를 Computer 클래스가 가리키게 해보자.

import java.util.List;
import java.util.ArrayList;

abstract class ComputerDevice {
    public abstract int getPrice();
    public abstract int getPower();
}

class Keyboard extends ComputerDevice {
    private int price;
    private int power;
    public Keyboard(int price, int power) {
        this.price = price;
        this.power = power;
    }
    public int getPrice() {
        return price;
    }
    public int getPower() {
        return power;
    }
}

class Body extends ComputerDevice {
    private int price;
    private int power;
    public Body(int price, int power) {
        this.price = price;
        this.power = power;
    }
    public int getPrice() {
        return price;
    }
    public int getPower() {
        return power;
    }
}

class Monitor extends ComputerDevice {
    private int price;
    private int power;
    public Monitor(int price, int power) {
        this.price = price;
        this.power = power;
    }
    public int getPrice() {
        return price;
    }
    public int getPower() {
        return power;
    }
}

class Computer extends ComputerDevice {
    private List<ComputerDevice> components = new ArrayList<>();
    public void addComponent(ComputerDevice component) {
        components.add(component);
    }
    public void removeComponent(ComputerDevice component) {
        components.remove(component);
    }
    @Override
    public int getPrice() {
        int price = 0;
        for (ComputerDevice component : components) {
            price += component.getPrice();
        }
        return price;
    }
    @Override
    public int getPower() {
        int power = 0;
        for (ComputerDevice component : components) {
            power += component.getPower();
        }
        return power;
    }
}

이렇게 되면 Speaker 클래스를 비롯한 다른 부품의 클래스가 생겨도 기존 코드를 수정하지 않고 사용할 수 있다.

추가적으로 이 글에 있는 일반화의 위임 부분을 보면 더 이해하기 쉬울 것 같다.

컴퍼지트 패턴 컬레보레이션

 

Component : 구체적인 부분, 즉 Leaf 클래스와 전체에 해당하는 Composite 클래스에 공통 인터페이스를 정의한 추상 클래스

Leaf : 구체적인 부분 클래스, Composite 객체의 부품으로 걸정한다.

Composite : 전체 클래스, 여러 개의 Component를 갖도록 정의한다. 즉, 여러 개의 Leaf 객체 및 Composite 객체를 부분으로 가질 수 있다.

728x90
Comments