그릇(복수)과 내용물(단수)을 동일시(= 혼합물, Composite)해서 재귀적인 구조 구축.
public abstract class Entry { public abstract String getName(); public abstract int getSize(); public Entry add(Entry entry) throws Exception { throw new Exception(); } public void printList() { printList(""); } protected abstract void printList(String prefix); @Override public String toString() { return getName() + " (" + getSize() + ")"; } }
내용물. 내부에는 다른 것을 넣을 수 없음.
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); } }
그릇. Leaf나 Composite 역할을 넣을 수 있음.
public class Directory extends Entry { private String name; private ArrayList<Entry> directory = new ArrayList<>(); public Directory(String name) { this.name = name; } @Override public String getName() { return name; } @Override public int getSize() { return Stream.of(directory).mapToInt(entry -> entry.size()).sum(); } /* Directory와 File을 같은 내용물로 간주 */ public Entry add(Entry entry) { directory.add(entry); return this; } @Override protected void printList(String prefix) { System.out.println(prefix + "/" + this); directory.forEach(entry -> entry.printList(prefix + "/" + name)); } }
public class Main { public static void main(String[] args) { try { 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)); rootdir.printList(); } catch (Exception e) { e.printStackTrace(); } } } /* /root (3) /root/bin (2) /root/bin/sub1 (10000) /root/bin/sub2 (20000) /root/tmp (0) /root/usr (0) */