Skip to content

컴포지트 패턴 #
Find similar titles

Structured data

Category
Programming

컴포지트 패턴(Composite Pattern) #

정의 #

객체를 트리구조로 구성하고 개별객체복합객체(Composite)가 구성되고 클라이언트에서는 두 객체를 동일하게 사용할 수 있다. 클라이언트는 Component 인터페이스, 추상클래스를 이용해서 개별객체 및 복합객체를 사용할 수 있다. 개별객체와 복합객체는 Component를 상속받으며 해당 메소드 중 연관된 메소드만 재정의한다. 개별객체는 실제 사용되는 말단객체이며, 복합객체는 하단에 또다른 객체의 집합을 구성하는 상위객체이다. 그러나 개별객체나 복합객체나 이를 관리하는 부분에서는 동일하게 취급한다.

사용법 #

  1. 객체의 구성 및 상하위 체계를 파악한다.
  2. 파악된 객체들을 트리구조로 설계한다.
  3. 개별객체와 복합객체는 공통으로 사용할 수 있는 메소드가 정의된 인터페이스, 추상클래스를 구현 또는 상속한다.

예제 #

Image

  1. Component
    • Composite하나를 포함하는 모든 component들의 추상화이다.
    • Composite에서 객체들을 위한 인터페이스를 정의한다.
  2. Leaf
    • Composition에서 leaf객체들을 나타낸다.
    • Component의 모든 메소드를 구현한다.
  3. Composite
    • Composite Component(component having children)
    • 자식들을 다루는 메소드를 제공한다.
    • 일반적으로 자식들에게 그 기능을 위임함으로써, Component의 모든 메소드를 구현한다.

      /* Component */
      public Interface Component{
        //객체와 복합객체가 구현해야 할 메소드 정의
          public void add(Component c); //객체 추가
          public void remove(Component c); //객체 제거
          public Componenet getChild(int i); //객체 얻기
          public String getName(); //객체명얻기
          public String exec();
      }
      
      /* Leaf */
      public class Leaf implements Component{
          //객체 클래스
          String name;
          public Leaf(String name){
          this.name=name;
          }
          public String getName(){
          ...
          }
          public String exec(){
          system.out.println("hello");
          }
      }
      
      /* Composite */
      public class Composite implements Component {
          //복합객체 클래스
          ArrayList<Component> coms = new ArrayList<Component>();
          String name;
          public Composite(String name) {
          this.name = name;
          }
          public void add(Component com) {
          coms.add(com);
          }
          public void remove(Component com) {
          coms.remove(com);
          }
          public Component getChild(int i) {
          return coms.get(i);
          }
          public String exec() {
          system.out.println("hi");
          }
      }
      
      /* 클라이언트 */
      public class Client {
          Component com;
          public Client(Component com) {
              thsi.com = com;
          }
          public void exec() {
              com.exec();
          }
      }
      
      /* 실행부 */
      public class TestComposite {
          public static void main(String [] args) {
           Component com1 = new Leaf("111");
           Component com2 = new Leaf("222");
           Component com3 = new Leaf("333");
           Component all = new Leaf("all");
      
          all.add(com1);
          all.add(com2);
          all.add(com3);
      
          com2.add(new Leaf("444"));
      
          Client c = new Client (all);
          c.exec();
          }
      }
      

비교 #

  • Composite vs Decorator vs Proxy

    • CompositeDecorator 패턴은 비슷한 구조를 갖고 있는데, 이 두 패턴 모두가 여러 객체를 조직화하기 위해 재귀적 합성 기법을 사용하기 때문이다.
    • 이런 구조적 유사성으로 Decorator 객체를 약화된 합성객체로 간주할 수도 있겠지만, 이는 Decorator의 중요한 특성을 놓치고 있는 것이다. 이 두 패턴의 공통성은 구조에서만 나타날 뿐 그 목적은 전혀 다르다.
    • Decorator 패턴은 상속없이 객체에 새로운 서비스를 추가하려는 목적을 갖는다. 그러므로 이미 만들어 둔 서비스 클래스들의 조합이 필요할 때마다 클래스를 생성해야 하는 문제를 해결해야 한다.
    • Composite 패턴의 경우는 클래스의 구조화에 초점이 맞추어진 것으로서 어떻게 하면 관련된 객체들을 하나의 인터페이스로 다룰 수 있도록 일관성을 부여할 것인가가 중요한 관건이다. 즉 여러 객체들을 하나의 객체로 통일시키고 싶은 것이다.
    • Decorator 패턴과 비슷한 구조를 갖는 것이 하나 더 있는데 바로 Proxy 패턴이다. 두 패턴 모두 다른 객체에 간접적으로 접근할 수 있고, 프록시와 데코레이터를 구현할 때 메시지를 전달할 상대 객체에 대한 참조자를 관리하는 공통점이 있지만, 두 패턴의 목적이 다르다.
    • Decorator와 같이 Proxy도 객체들을 합성하여 클라이언트에게는 동일한 인터페이스를 제공한다. 그러나 Proxy는 Decorator와 달리 동적으로 어떤 기능성을 추가했다 제거했다 하지는 않는다. Proxy의 목적은 서비스를 제공하는 대상에 대한 참조자를 직접관리하는 불편함을 해결하려는 것이다.
    • Decorator를 사용하는 목적은 컴파일할 때 모든 서비스의 객체를 다 결정할 수 없는 상황에서 적절하게 대응하기 위해서다.
    • 이런 차이들은 매우 중요하다. 구조가 비슷해 보여도 이들 패턴은 각기 서로 다른 객체지향 설계의 특정 문제를 해결하려는 목적을 갖고 있기 때문이다. 그렇다고 이들 패턴을 서로 합쳐서 사용할 수 없다는 것은 아니다. Proxy-Decorator 쌍은 Proxy에 추가적인 기능을 제공할 수 있고, Decorator-Proxy 쌍의 경우는 원격지에 떨어진 객체에도 새로운 기능을 추가할 수 있게 한다. 이처럼 패턴의 조합은 매우 유용하다.

Reference #

0.0.1_20140628_0