You are on page 1of 28

Java로 배우는 디자인패턴 입문

Chapter 12. Decorator


장식과 내용물의 동일시

교재: 자바언어로배우는디자인패턴입문(개정판)/YukiHiroshi저/김윤정역/영진닷컴

덕성여자대학교 컴퓨터학과
최승훈
01. Decorator 패턴

 예: 케이크
– 스펀지 케이크
– 딸기를 얹으면 => 스트로베리 케이크
– 화이트 초콜릿 + 초 => 생일 케이크

 중심이 되는 객체에, 장식과 같은 부가적인 기능을 하나씩


입혀서 좀 더 목적에 어울리는 객체를 만들자.

2
02. 예제 프로그램

 문자열 주위에 장식(-, +, | 문자)을 입혀 표시하는 프로그램

+------------------+
| hello, world. |
+------------------+

3
02. 예제 프로그램

4
02. 예제 프로그램

5
02. 예제 프로그램

 Display 클래스
– 여러 줄로 이루어진 문자열을 표시하기 위한 추상 클래스
– getColumns( ): 가로의 문자 수를 얻기 위한 메소드
– getRows( ): 세로의 줄의 수를 얻기 위한 메소드
– getRowText( ): 지정한 줄의 문자열을 얻기 위한 메소드
– show( )
 모든 줄을 화면에 표시하는 메소드
 Template Method 패턴이 적용됨

6
02. 예제 프로그램

 StringDisplay 클래스
– 한 줄의 문자열을 표시하는 클래스
– string 필드: 표시할 문자열을 저장함
– getColumns( ): string.getBytes().length 를 이용하여 문자열이
차지하는 바이트 수를 반환함
– getRows( ): 1을 반환함
– getRowText(int row): 입력 매개 변수 row가 0일 때만 string 필
드를 반환한다.
– 이 클래스는, 여러 케이크의 중심에 있는 스펀지 케이크에 해
당함

7
02. 예제 프로그램

 Border 클래스
– ‘장식’을 나타내는 추상 클래스
– Display의 하위 클래스로 정의됨
 장식(Border)이 내용물(Display)과 동일한 메소드를 가진다.
 장식과 내용물을 동일시 할 수 있다.
 장식 클래스를 내용물로 해서 또 다른 장식을 붙일 수 있다는 의

– display 필드: Display 형으로 선언됨
 장식이 감싸고 있는 “내용물”을 가리킨다.
 이 필드는, StringDisplay 뿐 만 아니라 Border 도 참조할 수 있다.
– 이유: Border도 Display의 하위 클래스이므로

8
02. 예제 프로그램

 SideBorder 클래스
– Border의 하위 클래스
– 구체적인 장식의 일종
– 문자열 좌우에 정해진 문자(BorderChar)로 장식한다.
– 생성자에서, 내용물(display)과 장식 문자(ch)가 지정됨
– getColumns( ): 내용물의 문자 수에 2를 더한다.
– getRows( ): 내용물의 getRows( )를 호출한다.
– getRowText( ): 내용물의 Text 양쪽에 장식 문자를 연결하여 반
환한다.

9
02. 예제 프로그램

 FullBorder 클래스
– Border의 하위 클래스
– 상하좌우에 장식을 한다.
– SideBorder와 달리, 장식할 문자가 미리 고정되어 있다.
– makeLine(char ch, int count): ch를 count 갯수 만큼 연속해서
문자열로 만드는 메소드
– getRowText(int row)
 입력인자 row가, 0 이거나 (내용물의 전체 줄 수 + 1)과 같으면
문자열 상단 또는 하단에 장식할 문자열을 만든다.

10
02. 예제 프로그램
 Main 클래스
– 동작 테스트용 클래스
– b1 객체: ‘Hello, world.’를 장식하지 않고 표시한 것
– b2 객체: b1에 대해 ‘#’ 문자로 좌우에 장식한 것
– b3 객체: b2에 대해 전체 장식을 한 것
– b4 객체: ‘안녕하세요’에 여려 겹 장식을 한 것

11
02. 예제 프로그램

show( ) 가 호출되면

1) +----------+ 출력하고,
2) + 내용물 + 출력하고,
3) +-----------+ 출력한다. # 내용물 # “Hello, world.”

12
03. 등장 역할

 Component의 역할
– 기능을 추가할 때 핵심이 되는 역할
– 스펀지 케이크에 해당함
– 예제에서는, Display 클래스가 해당됨

 ConcreteComponent의 역할
– Component 역할을 구현한 구체적인 클래스
– 구체적인 스펀지 케이크에 해당함
– 예제에서는, StringDisplay 클래스가 해당됨

13
03. 등장 역할

 Decorator(장식자)의 역할
– Component 역할과 동일한 인터페이스를 가짐
– 장식자이면서, 장식할 대상이 되기도 한다.
– 예제에서는, Border 클래스가 해당됨

 Concrete Decorator의 역할
– 구체적인 장식자
– 예제에서는, SideBorder와 FullBorder 클래스가 해당됨

14
03. 등장 역할

장식할 대상

장식자는, 장식할
대상을 포함한다.

장식자

15
04. 독자의 사고를 넓혀주는 힌트

 Border 클래스가 Display 클래스의 하위 클래스


– 장식을 나타내는 Border 클래스가, 내용물을 나타내는 Display
와 동일한 인터페이스(API)를 가진다.
– => 장식하는 클래스가, 다시 장식의 대상이 될 수 있다.

 Composite과 마찬가지로 재귀적인 구조임


– 예: FullBorder의 getRowText( )는 자신이 가지고 있는 Display
객체의 getRowText( ) 메소드를 호출한다.
– 목적이 서로 다르다.
 Composite 패턴은, container가 다시 내용물이 될 수 있다.
 Decorator 패턴은, 장식하는 클래스가, 다시 장식 대상이 될 수 있
다.

16
04. 독자의 사고를 넓혀주는 힌트

 내용물을 변경하지 않고, 기능을 추가할 수 있다


– 내용물을 변경하지 않고, 새로운 장식을 계속해서 부착할 수
있다.
– 포장되는 대상을 변경하지 않고, 기능을 추가할 수 잇다.
– Decorator 패턴에서는 위임이 사용된다.
 예: SideBorder의 getColumns 메소드 내에서는,
display.getColumns( ) 를 호출한다.

17
04. 독자의 사고를 넓혀주는 힌트

 단순한 장식으로도 다양한 기능을 추가할 수 있다.


– 간단한 구체적인 장식(ConcreteDecorator 역할)을 많이 준비
해 두고, 그것들을 자유롭게 조합하여 새로운 장식을 만들 수
있다.

18
04. 독자의 사고를 넓혀주는 힌트

 java.io 패키지와 Decorator 패턴


– 입출력 관련 패키지 java.io 에, Decorator 패턴이 사용됨
– 예:
 파일로부터 데이터 읽어 들일 때

Reader reader = new FileReader(“datafile.txt”);

 버퍼링 기능 추가

Reader reader = new BufferedReader(


new FileReader(“datafile.txt”);
);

19
04. 독자의 사고를 넓혀주는 힌트
 java.io 패키지와 Decorator 패턴
– 예(계속):
 줄 번호 관리 기능 추가 (setLineNumber(int), getLineNumber() 제공)

Reader reader = new LineNumberReader(


new BufferedReader(
new FileReader(“datafile.txt”);
)
);

 또 다른 조합 (버퍼링은 실행 안 함)

Reader reader = new LineNumberReader(


new FileReader(“datafile.txt”);
);

– javax.swing.border 패키지에도, 화면에 표시되는 컴포넌트에 추가할


수 있는 장식용 클래스들이 모여있다.

20
04. 독자의 사고를 넓혀주는 힌트

 작은 클래스가 증가함
– Decorator 패턴을 사용하면, 유사한 작은 클래스들이 많아지는
단점이 있다.
 이유: 하나의 큰 장식 대신, 작은 장식자들로 나누어지므로

21
05. 관련 패턴

 Adapter 패턴
 Strategy 패턴

22
06. 보강: 상속과 위임에 있어서의 동일시

 상속 – 하위 클래스와 상위 클래스의 동일 시
class Parent { class Child extends Parent {
... ...
void parentMethod( ) { void ChildMethod( ) {
... ...
} }
} }

– Child의 인스턴스를 Parent 형 변수에 그대로 대입하고, Parent


로 부터 상속받은 메소드를 그대로 불러낼 수 있다.
Parent obj = new Child( );
obj.parentMethod( );

 하위 클래스의 메소드를 불러내기 위해서는 type cast 가 필요함

Parent obj = new Child( );


((Child)obj).childMethod( );

23
06. 보강: 상속과 위임에 있어서의 동일시

 위임 – 자신과 위임할 곳을 동일 시
– Rose 와 Violet이 똑같은 메소드 method를 가지고 있고, Rose
는 Violet에게 위임한다.

class Rose { class Violet {


Violet obj = new Violet(); void method( ) {
void method( ) { ...
obj.method(); }
} }
}

– 문제점: Rose와 Violet이 똑같은 메소드인 method( )를 제공한


다는 조건이 소스 코드에 표현되어 있지 않다.
 다음 페이지에서 해결한다.

24
06. 보강: 상속과 위임에 있어서의 동일시

 위임 – 자신과 위임할 곳을 동일 시
– Flower 라는 공통 상위 클래스를 정의하면, ‘공통 정보 공유’가
명확해 진다.
abstract class Flower {
abstract void method( );
}

class Rose extends Flower {


class Violet extends Flower{ Violet obj = ...
void method( ) { void method( ) {
... obj.method();
} }
} }

25
06. 보강: 상속과 위임에 있어서의 동일시

 위임 – 자신과 위임할 곳을 동일 시
– Flower 는 인터페이스일 수 도 있다.

interface Flower {
abstract void method( );
}

class Rose implements Flower {


class Violet implements Flower{ Violet obj = ...
void method( ) { void method( ) {
... obj.method();
} }
} }
Flower 형으로 선언하는 것이
더 좋을 수 있다.

26
07. 요약

 객체를 차례차례 장식해서, 기능을 추가해 나가는 Decorator


패턴

27
연습 문제

 Q12-1
– 문자열 아래 위로 장식문자들을 추가하는 UpDownBorder 클래
스 만들기

 Q12-2
– 여러 줄의 문자열을 표시하는 MultiStringDisplay 클래스 만들기
– ConcreteComponent 역할 수행

28

You might also like