기록/패턴
Composite Pattern
jeongdalma
2020. 8. 5. 21:46
그릇과 내용물을 동일시해서 재귀적인 구조를 만들기 위한 디자인 패턴
Leaf(나뭇잎) 의 역할
Leaf는 '내용물'을 표시하는 역할을 하며 내부에는 다른 것을 넣을 수 없습니다.
예제 프로그램에서는 File클랙스가 이 역할을 합니다.
Composite(복합체) 의 역할
Composite는 '그릇'을 나타내는 역할을 하며 Leaf역할이나 Composite역할을 넣을 수 있습니다.
예제 프로그램에서는 Directory클래스가 이 역할을 합니다 .
Component의 역할
Leaf역할 과 Composite 역할을 동일시 하는 역할을 합니다.
Component는 Leaf역할과 Composite 역할에 공통적인 상위 클래스로 실현합니다.
예제 프로그램에서는 Entry클래스가 이 역할을 합니다.
Client(의뢰자) 의 역할
Composite패턴의 사용자입니다.
예제 프로그램에서는 Main 클래스가 이 역할을 합니다
Composite 역할이 포함하고 있는 Component 역할
(즉, Leaf역할이나 Composite 역할)을 부모에 대한 '자식'으로 간주합니다.
Main.java
public class Main {
public static void main(String[] args){
try{
System.out.println("Making root entries...");
Directory rootdir = new Directory("root");
Directory bindir = new Directory("bin");
Directory tmpdir = new Directory("tmp");
Directory userdir = new Directory("user");
rootdir.add(bindir);
rootdir.add(tmpdir);
rootdir.add(userdir);
bindir.add(new File("vi" , 10000));
bindir.add(new File("latex" , 20000));
rootdir.printList();
System.out.println("");
System.out.println("Making user entries...");
Directory Kim = new Directory("Kim");
Directory Lee = new Directory("Lee");
Directory Park = new Directory("Park");
userdir.add(Kim);
userdir.add(Lee);
userdir.add(Park);
Kim.add(new File("diary.html" , 100));
Kim.add(new File("Composite.java" , 200));
Lee.add(new File("memo.text" , 300));
Park.add(new File("game.doc" , 400));
Park.add(new File("junk.mail" , 500));
rootdir.printList();
}
catch(FileTreatmentException e){
}
}
}
File.java
public class File extends Entry {
private String name;
private int size;
public File(String name , int size){
this.name = name;
this.size = size;
}
@Override
public String getName() {
return name;
}
@Override
public int getSize() {
return size;
}
@Override
protected void printList(String prefix) {
System.out.println(prefix + "/" + this);
}
}
Directory.java
public class Directory extends Entry {
private ArrayList directory = new ArrayList();
private String name;
public Directory(String name){
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
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;
}
@Override
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);
}
}
}
Entry.java
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); // prefix를 앞에 붙여서 종류를 표시
public String toString(){
return getName() + " (" + getSize() + ")";
}
}
Console
Making root entries...
/root (30000)
/root/bin (30000)
/root/bin/vi (10000)
/root/bin/latex (20000)
/root/tmp (0)
/root/user (0)
Making user entries...
/root (31500)
/root/bin (30000)
/root/bin/vi (10000)
/root/bin/latex (20000)
/root/tmp (0)
/root/user (1500)
/root/user/Kim (300)
/root/user/Kim/diary.html (100)
/root/user/Kim/Composite.java (200)
/root/user/Lee (300)
/root/user/Lee/memo.text (300)
/root/user/Park (900)
/root/user/Park/game.doc (400)
/root/user/Park/junk.mail (500)