ETC/Design Pattern

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

장쫄깃 2023. 4. 13. 21:10
728x90

컴포지트 패턴 (Composite Pattern) 이란?


컴포지트 패턴 (Composite Pattern)은 객체 지향 디자인패턴 중 하나로, 복합 객체를 구성하는 개별적인 객체들을 모두 동일한 방법으로 다룰 수 있게 하는 패턴이다.

 

컴포지트 패턴은 트리 구조를 가진 객체들을 다루는데 특히 유용하다. 예를 들어, 파일 시스템에서 디렉토리와 파일을 구성하는 것과 같이, 여러 개의 객체가 포함된 복합 객체를 처리할 때 이용할 수 있다.

 

코드가 많으면, 코드가 복잡해지고, 많은 에러가 발생하게 된다. 이를 해결하기 위해 컴포지트 패턴은 개별 객체와 복합 객체를 동일한 인터페이스로 다룰 수 있다. 이 때, 개별 객체는 단순히 자기 자신을 다루는 방법으로 처리되고, 복합 객체는 자신에게 속한 개별 객체를 재귀적으로 다룰 수 있다. 이렇게 하면 클라이언트는 개별 객체와 복합 객체를 구분하지 않고 동일한 방식으로 사용할 수 있다.

 

컴포지트 패턴은 개별 객체와 복합 객체의 처리 방법이 다르지 않은 경우, 전체 - 부분 관계로 정의할 수 있다. 위에서 언급한 Directory - File과 같은 방식이다. 이렇게 전체 - 부분 관계를 효율적으로 정의할 수 있다.

 

컴포지트 패턴은 객체의 구조가 복잡할 때 유용하며, 객체 간의 결합도를 낮추어 유연성을 높일 수 있다. 또, 새로운 개별 객체나 복합 객체를 추가하더라도 클라이언트 코드를 수정할 필요가 없어 유지보수성이 좋다.

 

컴포지트 패턴

 

 

컴포지트 패턴의 장단점


  • 장점
    • 유연성
      • 객체의 구조를 변경하는데 유용하다.
      • 새로운 개별 객체나 복합 객체를 추가하더라도 클라이언트가 코드를 수정할 필요가 없다.
      • 객체 간 결합도를 낮춰 유연성을 높인다.
    • 단순성
      • 개별 객체와 복합 객체를 동일한 방식으로 다룰 수 있다.
      • 이로 인해 클라이언트의 코드가 단순해진다.
    • 재사용성
      • 객체를 구성하는 방식이 일관성있고, 재사용성이 높은 구조를 만들 수 있다.
    • 구조적 안정성
      • 복합 객체 내부의 구조를 안정적으로 유지할 수 있다.
      • 복합 객체에서 개별 객체를 제거하더라도, 객체 간의 관계가 깨지지 않는다.
  • 단점
    • 처리 비용
      • 복합 객체 내부의 모든 개별 객체를 처리해야 한다.
      • 이로 인해 처리 비용이 증가할 수 있다.
    • 설계 복잡성
      • 객체의 구조가 복잡한 경우에는 효과적이지만, 반대로 객체의 구조가 단순한 경우에는 오히려 설계의 복잡성을 증가시킬 수 있다.
    • 특정 상황에서의 한계
      • 개별 객체와 복합 객체가 서로 다른 인터페이스를 가지는 경우나, 복합 객체 내부 구조가 동적으로 변하는 경우에는 컴포지트 패턴을 사용하기 힘들다.

 

 

컴포지트 패턴 구현


// Component 인터페이스: 개별 객체와 복합 객체에 공통적인 메서드를 정의한다.
public interface Component {
    public void operation();
}

// Leaf 클래스: 개별 객체를 나타낸다.
public class Leaf implements Component {
    public void operation() {
        System.out.println("Leaf operation");
    }
}

// Composite 클래스: 복합 객체를 나타낸다.
public class Composite implements Component {
    private List<Component> components = new ArrayList<Component>();
    
    public void add(Component component) {
        components.add(component);
    }
    
    public void remove(Component component) {
        components.remove(component);
    }
    
    public void operation() {
        System.out.println("Composite operation");
        for (Component component : components) {
            component.operation();
        }
    }
}

// 클라이언트 코드
public class Client {
    public static void main(String[] args) {
        Component leaf1 = new Leaf();
        Component leaf2 = new Leaf();
        Component composite1 = new Composite();
        Component composite2 = new Composite();
        
        composite1.add(leaf1);
        composite2.add(leaf2);
        composite1.add(composite2);
        
        composite1.operation();
    }
}

 

위 코드에서는 Component 인터페이스를 정의하고, Leaf와 Composite 클래스에서 이를 구현한다. Composite 클래스에서는 List를 이용하여 여러 개의 Component를 정의하고, operation() 메소드에서는 내부의 모든 Component 객체에 대해 동일한 동작을 수행한다.

 

클라이언트 코드에서는 Leaf와 Composite 객체를 생성하여 Composite 객체에 추가하고, operation() 메소드를 호출하여 전체 구조를 처리한다.

728x90