02. 예제 프로그램

Download Report

Transcript 02. 예제 프로그램

Java로 배우는 디자인패턴 입문
Chapter 11. Composite
그릇과 내용물의 동일시
2004-1
01. Composite 패턴

컴퓨터의 파일 시스템
– 디렉토리(폴더) 안에 파일이나 또 다른 디렉토리가 존재한다.
– 디텍토리와 파일을 합쳐서, ‘디렉토리 엔트리’라고 한다.

재귀적인 구조
– 그릇 안에 내용물을 넣을 수도 있고, 작은 그릇을 넣을 수도 있
다. 작은 그릇 안에는 더 작은 그릇이나 내용물을 넣을 수도 있
다.

Composite 패턴
– 그릇과 내용물을 동일시해서 재귀적인 구조를 만드는 패턴
– composite: 혼합물, 복합물이라는 뜻
11. Composite
2
02. 예제 프로그램

파일과 디렉토리를 그림으로 표현하는 프로그램
11. Composite
3
02. 예제 프로그램

클래스 다이어그램
11. Composite
4
02. 예제 프로그램

기본 아이디어
– 트리 형태의 디렉토리 구조
– 클라이언트가
root에 대해서 getSize( )를 호출하면,
root
bin
dir2
a.txt
b.txt
– root는 자신의 내용물인 bin, tmp, usr에게
getSize( )를 호출한다.
– bin은 자신의 내용물인 dir2, a.txt, b.txt에게
getSize( )를 호출한다.
=> 재귀적 호출 이용
11. Composite
tmp
usr
5
02. 예제 프로그램

Entry 클래스
– 추상 클래스이고, 디렉토리 엔트리를 표현함
– File 클래스와 Directory 클래스를 하위 클래스로 가진다.
– 이름과 size를 가지고 있다.
– add( )
 디렉토리나 파일을 넣을 때 호출되는 메소드
 구현은 하위 클래스인 Directory 가 제공한다.
 Entry 클래스에서는 이 메소드가 호출되면 예외를 발생시킨다.
– printList( ), printList(String) : 오버로드됨
 호출될 때 인수의 모양에 따라 적절한 메소드가 실행됨
 printList(String)는 protected로 하위 클래스에서만 접근 가능함
– toString( ) : 이름과 size를 문자열로 표현함
11. Composite
6
02. 예제 프로그램

File 클래스
– 파일을 표현하는 클래스
– name과 size 속성
– 생성자 File( ): 이름과 크기를 인자로 받아들임
– getName( ): 파일의 이름을 반환함
– getSize( ): 파일의 크기를 반환함
– PrintList(String) 구현
 prefix와 자신의 문자열 표현을 ‘/’로 묶어서 표현함
 아래의 식은 모두 동일하다
prefix + “/” + this
prefix + “/” + this.toString( )
prefix + “/” + toString( )
11. Composite
7
02. 예제 프로그램

Directory 클래스
– name 필드 존재
– size 필드는 존재하지 않는다.
– getSize( )에서 디렉토리 사이즈를 동적으로 계산해서 반환한다.
 현재 디렉토리 클래스에 포함된 모든 요소(디렉토리 또는 파일)를
하나하나 꺼내서 그 사이즈를 합한다.
 아래 코드에서, entry가 File의 인스턴스나 Directory의 인스턴스
중 어떤 것이라도 상관없다.
– 이유: entry는 Entry 타입으로 선언되어 있고, Entry는 File이나
Directory의 부모 클래스이기 때문에 둘 다 참조할 수 있다.
size += entry.getSize( );
 entry가 디렉토리인 경우에는, 다시 이 디렉토리의 getSize( )가 재
귀적으로 호출된다. (Composite 패턴의 재귀적 구조와 일치함)
11. Composite
8
02. 예제 프로그램

Directory 클래스
– printList( )
 getSize 메소드와 마찬가지고 디렉토리에 포함된 Entry의 printList
를 재귀적으로 호출한다.
 entry가 File의 인스턴스인지, Directory의 인스턴스인지 상관없다.
– 그릇과 내용물이 동일시 된다.
11. Composite
9
02. 예제 프로그램

FileTreatmentException 클래스
– File에 add 메소드를 호출했을 때 발행하는 예외를 나타냄
– RuntimeException을 상속받아서 정의됨
– Entry 클래스에 add( ) 메소드가 정의되어 있고, File 클래스에
는 add( ) 메소드가 없다.
 따라서, File 클래스에 대해서 add( ) 메소드가 호출되면, Entry로
부터 상속받은 add( )가 실행된다.
 따라서, FileTreatmentException 예외가 발생된다.
11. Composite
10
02. 예제 프로그램

Main 클래스
– 교재 203 페이지와 같은 디렉토리 계층을 만든다.
– 그 후에, 이 디렉토리 구조를 출력한다.
rootdir.printList( );
 재귀적으로, 디렉토리 안에 있는 요소(디렉토리나 파일)의
printList( ) 가 호출된다.
11. Composite
11
03. 등장 역할

Leaf(잎사귀) 역할
– ‘내용물’에 해당되는 역할
– 이 안에는 다른 것을 넣을 수 없다
– 예제에서는 File 클래스가 해당됨

Composite(복합체) 역할
– ‘그릇’을 나타내는 역할
– Leaf와 Composite을 넣을 수 있다
– 예제에서는 Directory 클래스가 해당됨
11. Composite
12
03. 등장 역할

Component의 역할
– Leaf 역할과 Composite 역할을 동일시 하기 위한 역할
– Leaf와 Composite의 상위 클래스로 구현됨
– 예제에서는 Entry 클래스가 해당됨

Client(의뢰자)의 역할
– 예제에서 Main 클래스가 해당됨
11. Composite
13
03. 등장 역할
Composite이 포함하고 있는 요소를 얻어 오기 위한 메소드
=> 이 메소드는 자신이 포함하고 있는 요소들의 getChild
를 재귀적으로 호출한다.
=> 예제에서는, getSize( )와 printList( )가 여기에 해당된다.
11. Composite
14
04. 독자의 사고를 넓혀주는 힌트

복수와 단수의 동일시
– Composite 패턴은, 그릇과 내용물을 동일시하는 패턴
 그릇이, 또 다른 그릇의 내용물이 될 수 있다.
11. Composite
15
04. 독자의 사고를 넓혀주는 힌트

add를 어디에 두어야 하나?
– 방법1: Entry 클래스에서 구현하고, 에러로 처리한다.
 예제 프로그램이 여기에 해당됨
– 방법2: Entry 클래스에서 구현하고, 아무것도 실행하지 않는다.
– 방법3; Entry 클래스에서 추상 메소드로 선언은 하지만, 구현은
하지 않는다.
 하위 클래스에서 필요하면 정의하고, 필요하지 않으면 에러로 처
리한다.
– 방법4: Directory 클래스에만 넣는다.
 이 방법은, Entry 형의 변수에 add할 때, Directory 형으로 일일이
타입캐스트(형변환)해야 하는 번거로움이 있다.
(Directory) entry.add( );
11. Composite
16
04. 독자의 사고를 넓혀주는 힌트

재귀적 구조는 여러 곳에서 등장한다.
– 예: 윈도 안에는 자식 윈도를 가진다.
– 일반적으로 트리 구조는 Composite 패턴에 속한다.
11. Composite
17
05. 관련 패턴

Command 패턴 (22장)

Visitor 패턴 (13장)

Decorator 패턴 (12장)
11. Composite
18
06. 요약

그릇과 내용물을 동일시하고, 재귀적인 구조를 형성하는
Composite 패턴
11. Composite
19
연습 문제
11. Composite
20
02. 여러 가지 그림 템플릿

클래스 다이어그램
factoryMethod 역할
class Factory {
public Product createProduct(String name) {
return new Product(name);
}
}
Factory와 Product 수정 없이, 다른 종류의 ‘제품’과 ‘공장’을 추가로 만들수 있다.
=> Main 클래스(클라이언트)에서는, TV 제품이 필요한 경우, TVFactory 객체를 생성한 후에
TVFactory 객체의 create( ) 메소드를 호출하기만 하면 된다.
11. Composite
21