자바로 구현하는 컴포지트 패턴: 복합 객체와 단일 객체를 동일하게 다루기

자바로 구현하는 컴포지트 패턴: 복합 객체와 단일 객체를 동일하게 다루기

java-composite-pattern

자바에서 컴포지트 패턴이란?

컴포지트 패턴은 객체 지향 디자인 패턴 중 하나로, 복합 객체와 단일 객체를 동일하게 처리하기 위한 패턴입니다. 복합 객체는 또 다른 객체를 포함하는 객체로, 단일 객체는 더 이상 분해할 수 없는 객체입니다. 컴포지트 패턴은 복합 객체와 단일 객체를 동일한 방법으로 다룰 수 있도록 해줍니다.

컴포지트 패턴은 객체를 트리 구조로 구성할 때 많이 사용됩니다. 예를 들어, HTML 문서의 구조는 트리 구조로 되어 있습니다. HTML 문서는 여러 개의 태그로 구성되어 있으며, 각 태그는 자식 태그를 가질 수 있습니다. 이러한 구조를 컴포지트 패턴으로 구현하면, 복합 객체인 HTML 문서와 단일 객체인 각 태그를 동일한 방법으로 다룰 수 있습니다.

컴포지트 패턴은 다음과 같은 구성 요소로 이루어집니다.

  • Component: 복합 객체와 단일 객체를 포함하는 추상 클래스 또는 인터페이스입니다.
  • Leaf: 단일 객체를 나타내는 클래스입니다.
  • Composite: 복합 객체를 나타내는 클래스입니다. Component를 상속받으며, 자식 객체를 추가하거나 삭제할 수 있는 메서드를 구현합니다.

복합 객체와 단일 객체를 다루는 방법

컴포지트 패턴을 사용하면 복합 객체와 단일 객체를 동일한 방법으로 다룰 수 있습니다. 이를 위해서는 Component를 상속받는 Leaf 클래스와 Composite 클래스를 구현해야 합니다.

Leaf 클래스는 복합 객체의 단일 객체를 나타내는 클래스입니다. Leaf 클래스는 Component를 상속받으며, 자식 객체를 추가하는 메서드를 구현하지 않습니다.

Composite 클래스는 복합 객체를 나타내는 클래스입니다. Composite 클래스는 Component를 상속받으며, 자식 객체를 추가하거나 삭제하는 메서드를 구현합니다. 또한 Composite 클래스는 자식 객체들을 저장하기 위한 자료구조를 구현해야 합니다.

복합 객체와 단일 객체를 동일한 방법으로 다루기 위해서는 Component를 사용해야 합니다. Component는 Leaf와 Composite를 포함하는 추상 클래스 또는 인터페이스입니다. Component에서는 복합 객체와 단일 객체를 동일한 방법으로 다룰 수 있는 메서드들을 선언합니다. 이렇게 구현하면, 복합 객체와 단일 객체를 구분하지 않고 동일한 방법으로 다룰 수 있습니다.

자바로 구현하는 컴포지트 패턴 예제

다음은 자바로 구현한 컴포지트 패턴 예제입니다. 이 예제는 사칙연산을 표현하는 클래스를 구현합니다. 사칙연산은 덧셈, 뺄셈, 곱셈, 나눗셈으로 이루어져 있으며, 이를 트리 구조로 표현할 수 있습니다.

Component 클래스는 다음과 같이 구현됩니다. Component 클래스는 자식 객체를 추가하거나 삭제하는 메서드를 선언합니다.

public abstract class Component {
    protected List children = new ArrayList();

    public void add(Component component) {
        children.add(component);
    }

    public void remove(Component component) {
        children.remove(component);
    }

    public abstract int operate();
}

Leaf 클래스는 다음과 같이 구현됩니다. Leaf 클래스는 자식 객체를 추가하거나 삭제하는 메서드를 구현하지 않습니다. Leaf 클래스는 단일 숫자를 나타냅니다.

public class Leaf extends Component {
    private final int number;

    public Leaf(int number) {
        this.number = number;
    }

    @Override
    public int operate() {
        return number;
    }
}

Composite 클래스는 다음과 같이 구현됩니다. Composite 클래스는 자식 객체를 추가하거나 삭제하는 메서드를 구현합니다. Composite 클래스는 덧셈, 뺄셈, 곱셈, 나눗셈을 나타냅니다.

public class Composite extends Component {
    private final Operator operator;

    public Composite(Operator operator) {
        this.operator = operator;
    }

    @Override
    public int operate() {
        int result = operator.operate(children.get(0).operate(), children.get(1).operate());
        for (int i = 2; i < children.size(); i++) {
            result = operator.operate(result, children.get(i).operate());
        }
        return result;
    }

    public enum Operator {
        ADD {
            @Override
            public int operate(int a, int b) {
                return a + b;
            }
        },
        SUBTRACT {
            @Override
            public int operate(int a, int b) {
                return a - b;
            }
        },
        MULTIPLY {
            @Override
            public int operate(int a, int b) {
                return a * b;
            }
        },
        DIVIDE {
            @Override
            public int operate(int a, int b) {
                return a / b;
            }
        };

        public abstract int operate(int a, int b);
    }
}

이제 위에서 구현한 클래스들을 사용하여 사칙연산을 수행하는 예제를 작성해보겠습니다.

public class Main {
    public static void main(String[] args) {
        Component expression = new Composite(Composite.Operator.ADD);
        expression.add(new Leaf(1));
        expression.add(new Leaf(2));
        expression.add(new Leaf(3));

        System.out.println(expression.operate()); // 6
    }
}

위 예제는 덧셈 연산을 수행하는 예제입니다. Composite 클래스의 생성자로 덧셈 연산을 나타내는 Operator.ADD를 전달하고, Leaf 클래스를 생성하여 숫자 1, 2, 3을 전달합니다. 마지막으로 operate() 메서드를 호출하여 결과를 출력합니다.

컴포지트 패턴의 장단점과 활용 예시

컴포지트 패턴은 다음과 같은 장점을 가지고 있습니다.

  • 복합 객체와 단일 객체를 동일한 방법으로 다룰 수 있습니다.
  • 객체의 계층 구조를 표현하는 데 유용합니다.
  • 새로운 종류의 객체를 추가하기 쉽습니다.

컴포지트 패턴은 다음과 같은 단점을 가지고 있습니다.

  • 구현이 복잡할 수 있습니다.
  • 자식 객체를 추가하거나 삭제하는 작업이 많을 경우 성능이 저하될 수 있습니다.

컴포지트 패턴은 다음과 같은 예시에서 활용될 수 있습니다.

  • 트리 구조를 가진 데이터를 다룰 때
  • 메뉴나 버튼 같은 GUI 구성 요소를 다룰 때
  • 복잡한 계층 구조를 가진 클래스를 다룰 때

컴포지트 패턴은 객체 지향 디자인 패턴 중 하나로, 복합 객체와 단일 객체를 동일한 방법으로 다룰 수 있도록 해줍니다. 이를 위해 Component, Leaf, Composite 클래스를 구현하여 사용합니다. 컴포지트 패턴은 트리 구조를 가진 데이터나 GUI 구성 요소, 복잡한 계층 구조를 가진 클래스를 다룰 때 유용합니다. 하지만 구현이 복잡할 수 있고, 자식 객체를 추가하거나 삭제하는 작업이 많을 경우 성능이 저하될 수 있습니다.