제 홈페이지의 모든 글은 anti-nhn license에 따릅니다.



자바 디자인 패턴 7 - Composite

1. Composite 패턴은..

파일 데이터와 같은 일반적인 트리 구조의 데이터 타입을 만드는 것이 Composite 패턴입니다. Composite 패턴에서 주요등장 인물은 3개입니다. 첫째는 상위 컴포넌트. 둘째는 상위 컴포넌트를 상속 받으며 자식 컴포넌트를 가질 수 있는 Composite. 세째는 상위 컴포넌트를 상속 받으며, 하위 컴포넌트를 가질 수 없는 Leaf. 디렉토리가 Composite라면, 파일은 Leaf라고 보시면 됩니다.

2. 예제

이번 것은 소스가 좀 깁니다. 색칠된 부분만 중점적으로 보세요.

----------------- 상위 Component -----------------
package ch07_Composite;
import java.util.ArrayList;
import java.util.List;
public abstract class Component {
    private String componentName;
    protected List<Component> children = new ArrayList<Component>();
    public Component(String componentName) {
        this.componentName = componentName;
    }
    public String getComponentName() {
        return componentName;
    }
    public abstract void add(Component c);
    public List<Component> getChildren(){
        return children;
    }
    public String getString(){
        return getString(0);
    }
    private String getString(int depth){
        StringBuffer sb = new StringBuffer();
        if (this instanceof Composite) {
            for (int i = 0; i < depth; i++) {
                sb.append("  ");
            }
            sb.append("+"+getComponentName() +"\n");
            for (Component comp: children) {
                sb.append(comp.getString(depth+1));
            }
        }else{
            for (int i = 0; i < depth; i++) {
                sb.append("  ");
            }
            sb.append("-"+getComponentName()+"\n");
        }
        return sb.toString(); 
    }
}

----------------- 하위 Composite(하위 노드 가질 수 있음) -----------------
package ch07_Composite;
public class Composite extends Component {
    public Composite(String componentName) {
        super(componentName);
    }
    @Override
    public void add(Component c) {
        children.add(c);
    }
}

----------------- 하위 Leaf(하위 노드 가질 수 없음) -----------------
package ch07_Composite;
public class Leaf extends Component{
    public Leaf(String componentName) {
        super(componentName);
    }
    @Override
    public void add(Component c) {
        throw new UnsupportedOperationException();
    }
}

----------------- 테스트 클래스 -----------------
package ch07_Composite;

public class Test {
    public static void main(String[] args) {
        Composite main = new Composite("Main");
        Composite sub1 = new Composite("sub1");
        Composite sub2 = new Composite("sub2");
        Composite sub11 = new Composite("sub11");
        Composite sub12 = new Composite("sub12");
        Composite sub13 = new Composite("sub13");
        Composite sub21 = new Composite("sub21");
        Composite sub22 = new Composite("sub22");
        Leaf leaf14 = new Leaf("leaf14");
        Leaf leaf121 = new Leaf("leaf121");
       
        main.add(sub1);
        main.add(sub2);
        sub1.add(sub11);
        sub1.add(sub12);
        sub1.add(sub13);
        sub2.add(sub21);
        sub2.add(sub22);
        sub1.add(leaf14);
        sub12.add(leaf121);
       
        System.out.println(main.getString());
    }
}

----------------- 테스트 결과 -----------------
+Main
  +sub1
    +sub11
    +sub12
      -leaf121
    +sub13
    -leaf14
  +sub2
    +sub21
    +sub22

Component는 멤버 변수로 List<Component>를 가집니다. 이것이 트리 구조를 만드는 포인트입니다. Component에 있어서 중요한 메쏘드는 add()와 getChildren()입니다. add()의 인자는 Component 이고, getChildren()의 리턴 타입도 List<Component>입니다.  Composite인지 Leaf인지 구분하지 않습니다.

3. add와 getChildren 의 구현 방법

첫째, Component 에서 모든 것을 구현하고, Leaf에서는 add 메쏘드 호출 시 UnsupportedOperationException 을 던집니다. Component-Composite-Leaf 3 개의 구조가 아니라 Component-Leaf의 2개 구조만 있어도 됩니다. 그래서 구조가 간단해집니다. 그러나 Composite에는 있고, Leaf에는 없는 메쏘드를 구현할 방법이 없어집니다. 위의 예제는 단지 트리구조를 구현하는 것이라 상관없지만, 추가 기능을 구현할 가능성이 있는 경우는 이 방법을 쓰면 후에 문제가 생길 수 있습니다.
둘째, Component 에서는 abstract로 선언만 하고 Composite와 Leaf에서 구현을 합니다. Leaf에서는 첫번째 방법과 마찬가지로 UnsupportedOperationException 를 던지면 됩니다. 구조는 복잡하지만, 첫번째 방법에 비해 다른 기능 추가는 상대적으로 쉽습니다.

4. JAVA API에 있는 Composite

java.awt의 Container 는 Component를 상속 받고, Component를 다시 하위 객체로 가집니다. (여기서 하위는 상속의 하위 개념이 아닙니다. UI 구조상의 하위 구조입니다.) 예제에서 설명한 Leaf의 역할을 하는 객체들은 여러가지가 있습니다. Button, Text 등 우리가 알고 있는 일반적인 awt의 컴포넌트는 전부 포함된다고 보시면 됩니다.

by 삼실청년 | 2007/10/08 19:26 | 컴터질~ | 트랙백 | 핑백(2) | 덧글(9)

트랙백 주소 : http://iilii.egloos.com/tb/3838064
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Linked at java design patt.. at 2017/05/31 09:25

... nbsp;7. 자바 디자인 패턴 7 – Composite</A> 8. 자바 디자인 패턴 8 – Decorator 9. 자바 디자인 패턴 9 <a href="http://blog.sina.com.cn/s/blog_8e40db350102wt27.html">港股开户 &#8211; Chain of Responsibility& ... more

Linked at 자바 디자인 패턴 종류 &#8.. at 2017/09/26 09:15

... #8211; Template Method 5. 자바 디자인 패턴 5 – Singleton 6. 자바 디자인 패턴 6 – Strategy 7. 자바 디자인 패턴 7 – Composite 8. 자바 디자인 패턴 8 – Decorator 9. 자바 디자인 패턴 9 &#8211; Chain of Responsibili ... more

Commented by 갱일 at 2007/10/09 18:45
퍼간다잉~ 링크만..
Commented by AiRukia at 2009/05/18 01:12
디자인 패턴 입문자입니다.초보라서 학교 수업 따라가기가 벅찮는데,
님의 글을 읽고 좀 더 알기 쉽게 이해할 수 있었습니다.정말 감사드립니다.

(살짝 제 블로그에 링크 걸어둡니다.가끔씩 와서 공부하고 가겠습니다.^^)
Commented by 삼실청년 at 2009/05/19 20:47
^^ 넹.. 도움이 되셨으면 좋겠네요.
Commented by yong at 2009/12/04 14:22
죄송하지만 질문이 있는데요 Composite main = new Composite("Main"); 실행하면 상위컴포넌트에 componentName이 'Main'이 되고 main.add(sub1); 메소드 실행시에는 getChildren()이 실행되면서 children을 리턴하는데요... getChildren()를 실행했을때 상위컴포넌트 클래스 전체가 실행이 되나요?? 상위컴포넌트 add메소드 밑에 메소드들이 언제 실행되는지 모르겠네요.... 초짜라 ^^;;
Commented by 삼실청년 at 2009/12/08 15:06
클래스 전체가 실행된다는 게 무슨 뜻인지 모르겠습니다. 메쏘드 단위로 실행되지 클래스 전체가 실행되진 않습니다.
라인 단위로 실행과정을 추적하고 싶으신 것 같은데, 이클립스의 디버깅 기능을 이용해 보시면 될 것 같네요.
디버깅 시작될 라인 앞에 마우스 클릭하면 동그란 체크가 하나 생깁니다. 그리고 실행 버튼 옆에 벌레 모냥 클릭해서 디버깅 시작하시면, 실행되는 라인 단위로 추적할 수 있습니다.
Commented by 잡초y at 2012/07/03 14:29
저는 해드퍼스트 디자인패턴 책을 보고 이해가 안되서 너무 머리아팠는데 삼실님의 블로그를 보고 행복해 하고 있는 한 소년DBA입니다.. ! 좋은 자료 감사합니다!
Commented by 삼실청년 at 2012/07/04 01:19
dba가 디자인패턴까지 보시다니.
어쨌거나 행복하시다니 저도 뿌듯하네요^^
찾아주셔서 감사합니다.
Commented by at 2015/01/29 15:52
좋은 정리 감사합니다.
Commented by 박영준 at 2016/01/29 10:21
너무 잘 읽고 많이 배웁니다.
검색해서 몇개 읽다가 그냥 첫번째 글부터 정주행하고 있습니다 ;
이러게 좋은 내용을 작성하신지 9년 지난 시점에 본다는게 슬프네여 ㅎ

:         :

:

비공개 덧글

◀ 이전 페이지          다음 페이지 ▶