Java

[Design Pattern] 복합체 패턴(Composite Pattern)

구루싸 2020. 7. 5. 19:38
반응형
SMALL

어느 덧 7월 2020년도 하반기로 접어들었습니다

남은 반년 화이팅하시고

좋은 성과와 행복이 가득하시길 기원합니다

아무튼 오늘의 학습 주제는 복합체 패턴입니다

컴퓨터 파일 시스템(File System)에는

디렉터리(Directory) 혹은 폴더(Folder)가 있고

그 안에는 다른 디렉터리나 폴더가 있을 수 있고

파일도 있을 수 있습니다

그런데 어떤 디렉터리 안을 조회할 때

이것이 디렉터리 인지 파일인지 모르지만

이 둘을 하나의 디렉터리 엔트리(Entry)로

간주하여 재귀적인 구조를

이루게하면 편리해질 수 있습니다

이번 학습 주제인 복합체 패턴(Composite Pattern)은

이와 같은 모습으로 만들기 위한 패턴입니다

오늘도 복합체 패턴에 등장하는

역할들을 정리하고 시작하겠습니다

역할 설명
Leaf(나뭇잎) Leaf는 '내용물'을 표시하는 역할을 하며 내부에는 다른 것을 넣을 수 없음
Composite(복합체) Composite은 '그릇'을 나타내는 역할을 하며 Leaf나 Composite 역할을 넣을 수 있음
Component(컴포넌트) Leaf와 Composite 역할을 동일시하는 역할
Client(의뢰자) Composite 패턴의 사용자

자 이제 구현을 해봐야겠죠?^^;

1. 추상 클래스(Abstract Class) Entry.java

package compositePattern;

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() + ")";
	}
}

2. 클래스(Class) Directory.java

package compositePattern;
import java.util.*;
public class Directory extends Entry {
	private String name;
	private ArrayList<Entry> directory = new ArrayList<Entry>();
	public Directory(String name) {
		this.name = name;
	}
	public String getName() {
		return name;
	}
	public int getSize() {
		int size = 0;
		Iterator<Entry> 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<Entry> it = directory.iterator();
		while ( it.hasNext() ) {
			Entry entry = (Entry) it.next();
			entry.printList(prefix + "/" + name);
		}
	}
}

3. 클래스(Class) File.java

package compositePattern;

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);
	}
}

4. 클래스(Class) FileTreatmentException.java

package compositePattern;

public class FileTreatmentException extends RuntimeException {
	public FileTreatmentException() {
	}
	public FileTreatmentException(String msg) {
		super(msg);
	}
}

5. 클래스(Class) Test.java

import compositePattern.*;
public class Test {
	public static void main(String[] args) {
		/* composite Pattern */
		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 Park = new Directory("Park");
			Directory Sa = new Directory("Sa");
			usrDir.add(Kim);
			usrDir.add(Lee);
			usrDir.add(Park);
			usrDir.add(Sa);
			Kim.add(new File("diary.html", 100));
			Lee.add(new File("memo.txt", 200));
			Park.add(new File("game.c", 300));
			Sa.add(new File("Composite.java", 400));
			rootDir.printList();
		} catch ( FileTreatmentException e ) {
			e.printStackTrace();
		}
	}
}

이번 Composite 패턴은 비교적 간단했네요-_-

부연 설명을 할 부분은 아무래도

add 메소드의 구현 방법일 것 같은데요

구현 방법을 보면 다음과 같습니다

1. Entry 클래스에서 구현하고 예외 제공한다.
2. Entry 클래스에서 구현하고 아무것도 실행하지 않는다.
3. Entry 클래스에서 선언은 하지만 구현은 하지 않는다. ==> File 클래스에서 add 메소드를 정의해야한다.
4. Directory 클래스에만 넣는다. ==> add할 때마다 Directory형으로 캐스트해야한다.

이것으로 오늘의 학습을 마치도록 하겠습니다

그럼 이만-_-

반응형
LIST