OOP거듭나기

구조패턴 - 컴포지트 패턴

손병환 2006. 9. 26. 10:55

이번에는 컴포지트 패턴에 대해서 적을까 한다.

이 녀석을 보면 이전에 대학교때 자료구조 시간에 배웠던 Double Linked List생각이 난다.

현재 오브제트를 자기 참조를 해서 포인트로 다음 오브젝트에 연결시키던 것이 생각이 난다.

 

부모 클래스를 상속받은 자식 클래스가 부모 클래스를 멤버로 가지게 된다.

이 부분은 링크드 리스트 같은 구조에 대한 이해가 부족하면 쉽게 이해하기도 적용하기도 힘든 부분 가운데 하나다.

 

특히 A클래스가 자신의 인스턴스를 A클래스에서 호출할 때와 마찬가지라고나 할까?

클래스가 생성될 때 메모리 구조를 이해할 경우에는 아마도 더 쉽게 이해가 되겠지만,

메모리와의 관계에 대해서 이해가 부족한 경우에는 일단은 예제와 클래스 다이어그램을 이용해서

이해를(이해라기 보다는 암기를.. --;;;) 하는 편이 좋을 것 같다.

 

가장 현실적이면서도 접근하기 쉬운 것이 현재 윈도우에서 사용하고 있는 트리구조...

즉, �쌕끼(Explorer)의 왼쪽에 있는 트리구조가 바로 이러한 컴포지트 패턴을 이용해서

손쉽게 구현이 가능하다. 아래의 소스에는 단지 추가, 삭제, 표시만 존재하는데

검색이라는 기능 또한 넣어 둔다면 그야말로 완벽한 트리구조가 아닐까?

 

이전에만 해도 이런 형태를 구현할려면 Recursive함수를 사용해서 만들어야 했지만

조금만 머리를 굴려보면 컴포지트 클래스를 이용해서 좀 더 쉽게 접근할 수 있다.

 

일단은 클래스 A에서 클래스 A에 대한 인스턴스를 생성시켜서 어떤 현상이 발생하는지를

확인해 두면 콤포지트 패턴에 대해서 거의 이해했다고 봐도 과언이 아닐까 한다.

앞으로 이런 부분들이 자주 나오게 될 것이다. 지금부터라도 확실하게 개념을 파악해서

넘어가자. (헉 모르겠다구요... 그럼 그냥 외워버리세요... 그냥 외워서 자주 사용하다 보면 자연스럽게

몸에 배여버리니까요... 쩝~~~ 회피성 발언... )

 

 

 

 

 

// Composite pattern -- Structural example

using System;
using System.Collections;

namespace DoFactory.GangOfFour.Composite.Structural
{

  // MainApp test application

  class MainApp
  {
    static void Main()
    {
      // Create a tree structure
      Composite root = new Composite("root");
      root.Add(new Leaf("Leaf A"));
      root.Add(new Leaf("Leaf B"));

      Composite comp = new Composite("Composite X");
      comp.Add(new Leaf("Leaf XA"));
      comp.Add(new Leaf("Leaf XB"));

      root.Add(comp);
      root.Add(new Leaf("Leaf C"));

      // Add and remove a leaf
      Leaf leaf = new Leaf("Leaf D");
      root.Add(leaf);
      root.Remove(leaf);

      // Recursively display tree
      root.Display(1);

      // Wait for user
      Console.Read();
    }
  }

  // "Component"

  abstract class Component
  {
    protected string name;

    // Constructor
    public Component(string name)
    {
      this.name = name;
    }

    public abstract void Add(Component c);
    public abstract void Remove(Component c);
    public abstract void Display(int depth);
  }

  // "Composite"

  class Composite : Component
  {
    private ArrayList children = new ArrayList();

    // Constructor
    public Composite(string name) : base(name)
    {  
    }

    public override void Add(Component component)
    {
      children.Add(component);
    }

    public override void Remove(Component component)
    {
      children.Remove(component);
    }

    public override void Display(int depth)
    {
      Console.WriteLine(new String('-', depth) + name);

      // Recursively display child nodes
      foreach (Component component in children)
      {
        component.Display(depth + 2);
      }
    }
  }

  // "Leaf"

  class Leaf : Component
  {
    // Constructor
    public Leaf(string name) : base(name)
    {  
    }

    public override void Add(Component c)
    {
      Console.WriteLine("Cannot add to a leaf");
    }

    public override void Remove(Component c)
    {
      Console.WriteLine("Cannot remove from a leaf");
    }

    public override void Display(int depth)
    {
      Console.WriteLine(new String('-', depth) + name);
    }
  }
}