1. 예제 프로그램 - 파일과 디렉토리를 그림으로 표현하는 프로그램
<Entry.java>
package ch11.Sample;
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() + ")";
}
}
<File.java>
package ch11.Sample;
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);
}
}
<FileTreatmentException.java>
package ch11.Sample;
public class FileTreatmentException extends RuntimeException {
public FileTreatmentException() {
}
public FileTreatmentException(String msg) {
super(msg);
}
}
<Directory.java>
package ch11.Sample;
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;
// 자신이 가지고 있는 모든 엔트리에 대해서, getSize( )호출하여 더한다.
Iterator it = directory.iterator();
while (it.hasNext()) {
// entry는 Entry 타입으로 선언되어 있고,
// Entry는 File이나 Directory의 부모 클래스이기 때문에 둘 다 참조할 수 있다.
Entry entry = (Entry) it.next();
// entry가 디렉토리인 경우에는, 다시 이 디렉토리의 getSize( )가 재귀적으로 호출된다.
size += entry.getSize();
// => 그릇과 내용물이 동일시 된다.
}
return size;
}
public Entry add(Entry entry) { // 엔트리의 추가
// 입력인자로 들어온 Entry(File 또는 Directory 객체)를 벡터에 저장한다.
directory.add(entry);
return this;
}
protected void printList(String prefix) { // 엔트리의 일람
System.out.println(prefix + "/" + this);
// 자신이 가지고 있는 모든 엔트리에 대해서, printList( )호출한다.
Iterator it = directory.iterator();
while (it.hasNext()) {
Entry entry = (Entry) it.next();
entry.printList(prefix + "/" + name);
}
}
}
<Main.java>
package ch11.Sample;
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 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();
System.out.println("");
System.out.println("Making user entries...");
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();
}
}
}
2. 연습 문제 - Entry(또는 하위클래스)의 인스턴스로부터 '풀패스'를 얻는 기능을 추가하는 방법
<Entry.java>
package ch11.A2;
public abstract class Entry {
protected Entry parent;
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() + ")";
}
public String getFullName() {
StringBuffer fullname = new StringBuffer();
Entry entry = this;
do {
fullname.insert(0, "/" + entry.getName());
entry = entry.parent;
} while (entry != null);
return fullname.toString();
}
}
<File.java>
package ch11.A2;
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);
}
}
<Directory.java>
package ch11.A2;
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);
entry.parent = this;
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);
}
}
}
<FileTreatmentException.java>
package ch11.A2;
public class FileTreatmentException extends RuntimeException {
public FileTreatmentException() {
}
public FileTreatmentException(String msg) {
super(msg);
}
}
<Main.java>
package ch11.A2;
public class Main {
public static void main(String[] args) {
try {
Directory rootdir = new Directory("root");
Directory usrdir = new Directory("usr");
rootdir.add(usrdir);
Directory Kim = new Directory("Kim");
usrdir.add(Kim);
File file = new File("Composite.java", 100);
Kim.add(file);
rootdir.printList();
System.out.println("");
System.out.println("file = " + file.getFullName());
System.out.println("Kim = " + Kim.getFullName());
} catch (FileTreatmentException e) {
e.printStackTrace();
}
}
}