2011년 5월 23일 월요일

The Composite Pattern

8. The Composite Pattern
개발자들은 종종 컴포넌트가 개별적인 객체로 간주될 수 있거나 일련의 객체를 표현할 수 있는 시스템을 개발하게 된다. Composite 패턴은 위의 두 가지 경우에 모두 적용될 수 있도록 설계된 패턴이다. Composite 패턴은 부분에서 전체에 이르는 계층 구조를 구축하거나 Tree형 자료 명세 내역을 생성하기 위해 사용될 수 있다. 예를 들어 디렉토리와 파일을 합해서 디렉토리 엔트리로 취급하듯이 그릇과 내용물을 같은 종류로 취급하는 경우다. 이와 같이 특정 객체들과 그것들을 포함하는 객체들을 동일하게 다룰 수 있게 해주는 패턴을 Composite 패턴이라고 한다.
구조
*


역할
v Leaf의 역할
‘내용물’을 나타내는 역할, 이 안에는 다른 ‘내용물’을 넣을 수 없습니다. 파일과 디렉토리 관계에서 보면 ‘파일’에 해당합니다.
v Composite의 역할
‘그릇’을 나타내는 역할, 이 안에는 ‘내용물’과 다른 ‘그릇’이 포함될 수 있습니다. 파일과 디렉토리 관계에서 ‘디렉토리’에 해당합니다.
v Component의 역할
Leaf역할과 Composite 역할을 동일시하기 위한 일을 합니다. Component의 역할은 Leaf역할과 Composite역할의 공통의 상위 클래스로서 실현됩니다.
v Client의 역할
Composite 패턴의 이용자 입니다.
의도
전체 – 부분을 표현하기 위해 객체들을 트리구조로 묶을 수 있다. 클라이언트 코드는 각 개별적인 객체(부분)와 다른 객체를 포함하는 객체(전체)를 동일한 인터페이스를 통해 사용할 수 있다.
적용시기
전체와 부분을 동일하게 다루길 원할 때 적용 합니다.
결론
Composite 패턴은 단순 객체 및 복잡한 객체의 계층 구조에 대한 클래스를 정리할 수 있게 하여 클라이언트의 프로그램에서는 모두 같은 종류로 나타낸다. 노드와 리프가 같은 방식으로 관리되기 때문에 이렇게 단순화해서 클라이언트도 그것에 맞추어 간단해질 수 있다.
Composite 패턴은 개발자의 컬렉션에 새로운 컴포넌트를 추가하기가 매우 쉬운데, 해당 패턴이 유사한 프로그램밍 인터페이스를 지원하는 한 이것은 계속 유효하다. 반면에 Composite 패턴은 시스템을 지나치게 일반화한다는 단점이 있다. 이런 단점이 일반적으로 바람직하게 용인되는 경우 아마도 특정 클래스를 제한할 때 어려움을 겪게 될 것 이다.
구현상의 문제점
v 컴포넌트의 정렬 – 일부 프로그램에서는 컴포넌트의 배열 순서가 중요한 요소로 작용할 수 있다. 만약 부모 요소에 추가될 때의 정렬 순서와 실제 컴포넌트의 정렬 순서에 차이가 있을 경우 부모 요소는 반드시 추가된 컴포넌트들을 올바른 순서로 정렬하기 위해 별도의 작업을 수행해야 한다. 예를 들어 , 원본 Vector 요소를 알파벳순으로 정렬한 후 Enumerator에 수정된 Vector정보를 되돌릴 수 있다.
v 케싱 결과 – 일련의 자식 컴포넌트에서 연산되어야 하는 데이터를 종종 요청하는 경우 부모요소에서 연산 결과를 케싱하는 것이 도움이 될 수도 있다. 그러나 해당 연산 적업이 상대적인 면에서 집중적으로 수행되어 개발자가 기본 데이터를 변경하지 않는다는 것을 확신할 수 있는 경우가 아닐 때는 이런 방법이 필요없을수도 있다.


예제소스
*


예제 소스
public abstract class Entry {
public abstract String getName();
public abstract int getSize();
public Entry add(Entry entry) throws FileTreatmentException {
throw new FileTreatmentException();
}
public void printList() {
printList("");
}
protected abstract void printList(String prefix);
public String toString() {
return getName() + " (" + getSize() + ")";
}
}
import java.util.Iterator;
import java.util.Vector;
public class Directory extends Entry {
private String name;
private Vector directory = new Vector();
public Directory(String name) {
this.name = name;
}
public String getName() {
return name;
}
public int getSize() {
int size = 0;
Iterator it = directory.iterator();
while (it.hasNext()) {
Entry entry = (Entry)it.next();
size += entry.getSize();
}
return size;
}
public Entry add(Entry entry) {
directory.add(entry);
return this;
}
protected void printList(String prefix) {
System.out.println(prefix + "/" + this);
Iterator it = directory.iterator();
while (it.hasNext()) {
Entry entry = (Entry)it.next();
entry.printList(prefix + "/" + name);
}
}
}
public class File extends Entry {
private String name;
private int size;
public File(String name, int size) {
this.name = name;
this.size = size;
}
public String getName() {
return name;
}
public int getSize() {
return size;
}
protected void printList(String prefix) {
System.out.println(prefix + "/" + this);
}
}
public class FileTreatmentException extends RuntimeException {
public FileTreatmentException() {
}
public FileTreatmentException(String msg) {
super(msg);
}
}
public class mainClass {
public static void main(String[] args) {
mainClass client = new mainClass();
client.exec();
}
public void exec() {
try {
System.out.println("Making root entries...");
Directory rootdir = new Directory("root");
Directory bindir = new Directory("bin");
Directory tmpdir = new Directory("tmp");
Directory usrdir = new Directory("usr");
rootdir.add(bindir);
rootdir.add(tmpdir);
rootdir.add(usrdir);
bindir.add(new File("vi", 10000));
bindir.add(new File("latex", 20000));
Directory Kim = new Directory("Kim");
Directory Lee = new Directory("Lee");
Directory Kang = new Directory("Kang");
usrdir.add(Kim);
usrdir.add(Lee);
usrdir.add(Kang);
Kim.add(new File("diary.html", 100));
Kim.add(new File("Composite.java", 200));
Lee.add(new File("memo.tex", 300));
Kang.add(new File("game.doc", 400));
Kang.add(new File("junk.mail", 500));
rootdir.printList();
} catch(FileTreatmentException e) {
e.printStackTrace();
}
}
}


관련패턴
  • Command : 매크로커맨드를 만들 때 Composite 패턴이 사용됩니다.
  • Visitor : Composite 를 순환하여 처리하는데 사용됩니다.
  • Decorator : Composite는 그룻과 , 내용물을 동일시 하고, Decorator 패턴은 장식과 내용물을 동일시합니다.

댓글 없음:

댓글 쓰기

블록체인 개요 및 오픈소스 동향

블록체인(block chain) 블록체인은 공공 거래장부이며 가상 화폐로 거래할때 발생할때 발생할 수 있는 해킹을 막는 기술. 분산 데이터베이스의 한 형태로, 지속적으로 성장하는 데이터 기록 리스트로서 분산 노드의 운영자에 의한 임의 조작이 불가...