Composite Pattern의 목적은 객체의 계층 구조를 표현하고 각 객체를 동일한 인터페이스로 독립적으로 처리할 수 있도록 하는 것이다. 이를 통해 클라이언트는 개별 객체(Leaf)와 객체 그룹(Composite)을 같은 방식으로 다룰 수 있다.
Composite Pattern의 기본 구성은 Component
, Leaf
, 그리고 Composite
클래스로 이루어진다. 아래 그림은 Composite Pattern의 클래스 다이어그램을 나타낸다.
Component
는 Leaf
와 Composite
클래스에서 공통적으로 사용되는 메서드를 선언한 추상 클래스 또는 인터페이스다. 여기서 메서드들은 기본적으로 예외를 발생시키도록 구현되어, Leaf
가 사용하지 않는 메서드 호출 시 예외가 발생하게 된다.
public abstract class Component {
public void operation() {
throw new UnsupportedOperationException();
}
public void add(Component component) {
throw new UnsupportedOperationException();
}
public void remove(Component component) {
throw new UnsupportedOperationException();
}
public Component getChild(int i) {
throw new UnsupportedOperationException();
}
}
Leaf 클래스는 트리의 말단 요소를 의미하며, 개별 객체를 나타낸다. Component 클래스에서 필요한 메서드만 구현하며, 다른 메서드를 호출할 경우 UnsupportedOperationException이 발생하게 된다.
public class Leaf extends Component {
private String name;
public Leaf(String name) {
this.name = name;
}
@Override
public void operation() {
System.out.println("Leaf " + name + " operation 수행");
}
}
Composite 클래스는 여러 Component 객체를 포함할 수 있으며, 이 객체들을 재귀적으로 처리하는 역할을 한다. add, remove, getChild 메서드를 구현하여 자식 컴포넌트를 관리할 수 있다.
import java.util.ArrayList;
import java.util.Iterator;
public class Composite extends Component {
private ArrayList<Component> components = new ArrayList<>();
private String name;
public Composite(String name) {
this.name = name;
}
@Override
public void operation() {
System.out.println("Composite " + name + " operation 수행");
for (Component component : components) {
component.operation();
}
}
public void add(Component component) {
components.add(component);
}
public void remove(Component component) {
components.remove(component);
}
public Component getChild(int i) {
return components.get(i);
}
}
부모만 자식을 참조할 것인가, 자식도 부모를 참조해야 할 것인가?
구조를 구현하기 전에 자식이 부모를 참조해야 하는지 고려하는 것이 중요하다.
어떤 클래스가 자식을 관리할 것인가?
일반적으로 Composite 클래스가 자식을 관리하지만, 관리 함수가 Component 클래스에 있는 경우 장단점을 고려해야 한다.
1.Transparency 방식
Component 클래스에 add, remove, getChild 같은 자식 관리 메서드를 선언하여, Leaf와 Composite 클래스를 구분하지 않고 동일한 Component로 다룰 수 있게 한다.
Composite Pattern은 객체의 계층 구조를 동일한 인터페이스로 관리할 수 있게 하여 클라이언트 코드의 복잡성을 줄인다. Composite와 Leaf 객체를 구분하지 않고, 공통된 인터페이스를 통해 처리하는 점에서 구조의 일관성을 유지할 수 있는 장점이 있다. 이러한 구조 덕분에 클라이언트는 복잡한 계층 구조를 신경 쓰지 않고 단순히 Component로 다룰 수 있어, 관리와 확장성을 확보할 수 있다.