덕성여대 컴퓨터학부 02. 예제 프로그램

Download Report

Transcript 덕성여대 컴퓨터학부 02. 예제 프로그램

Java로 배우는 디자인패턴 입문
Chapter 17. Observer 패턴
상태의 변화를 통지한다
2004-1
덕성여자대학교 컴퓨터학부
01. Observer 패턴

observer
– 관찰자
– 관찰 대상의 상태가 변하면, 관찰자에게 통지된다.
– 객체의 상태 변화에 따른 처리를 기술할 때 유용하게 사용된다.
덕성여대 컴퓨터학부
2
02. 예제 프로그램

수를 많이 생성하는 객체를 관찰자가 관찰해서, 그 값을 표
시하는 프로그램

관찰자의 종류에 따라 표시 방법이 다르다
– DigitObserver: 값을 숫자로 표시함
– GraphObserver: 값을 간이 그래프로 표시함
덕성여대 컴퓨터학부
3
02. 예제 프로그램
덕성여대 컴퓨터학부
4
02. 예제 프로그램

클래스 다이어그램
관찰자
관찰대상
덕성여대 컴퓨터학부
5
02. 예제 프로그램

Observer 인터페이스
– 관찰자를 표현하는 인터페이스
– update(NumberGenerator)
 NumberGenerator가 “나의 내용이 갱신되었습니다. 표시도 갱신해
주세요”라고 관찰자에게 알려줄 때 호출하는 메소드
덕성여대 컴퓨터학부
6
02. 예제 프로그램

NumberGenerator 클래스
– 수를 생성하는 클래스
– execute( ), getNumber( ): 추상 메소드
– observer 필드: NumberGenerator를 관찰하고 있는 Observer들
을 보관하고 있는 필드
– addObserver(Observer)
 Observer를 추가할 때 호출하는 메소드
– deleteObserver(Observer)
 Observer를 삭제할 때 호출하는 메소드
– notifyObservers( )
 Observer 전원에게, “나의 내용이 갱신되었기 때문에 당신의 표시
도 갱신해주세요”라고 알려주는 메소드
 Observer들의 update(this) 메소드를 차례차례 호출한다.
덕성여대 컴퓨터학부
7
02. 예제 프로그램

RandomNumberGenerator 클래스
– NumberGenerator의 하위 클래스
– 난수를 생성한다
 java.util.Random 클래스 이용
– number 필드: 생성된 난수를 저장하는 변수
– getNumber( ): number 필드의 값을 반환함
– execute( ):
 0~49 까지의 난수 20개를 생성하고, 그 때마다 notifyObservers를
호출하여, 관찰자들에게 통지한다.
 Random 클래스의 nextInt( ) 이용함
덕성여대 컴퓨터학부
8
02. 예제 프로그램

DigitObserver 클래스
– Observer 인터페이스를 구현한 구체적인 관찰자
– 관찰한 수를 ‘숫자’로 표시함
– update(NumberGenerator)
 인자로 전달된 NumberGenerator의 getNmber( )를 이용하여 수를
얻어서 화면에 출력한다.
 출력한 후, 표시된 모습을 잘 알 수 있도록 Thread.sleep( )을 이용
하여 스피드를 늦춘다.
– Thread.sleep(100)
• (100/1000 = 0.1 초) 동안 CPU를 반환하고 쉬겠다는 뜻
덕성여대 컴퓨터학부
9
02. 예제 프로그램

GraphObserver 클래스
– Observer 인터페이스를 구현한 구체적인 관찰자
– 관찰한 수를 ‘간단한 그래프’로 표시함
 관찰한 숫자만큼의 ‘*’를 출력한다
덕성여대 컴퓨터학부
10
02. 예제 프로그램

Main 클래스
– RandomNumberGenerator 인스턴스 1 개 생성함
– 관찰자 2개 생성함
– RandomNumberGenerator에 관찰자 2개를 등록함
– RandomNumberGenerator의 execute( )를 이용해서 수를 생성
한다
 난수가 발생될 때마다, 관찰자들은 각자의 방식대로 수를 ‘표시’한
다.
덕성여대 컴퓨터학부
11
03. 등장 역할

Subject(관찰 대상자) 역할
– ‘관찰되는 쪽’을 나타냄
– Observer 역할을 등록하는 메소드와 삭제하는 메소드를 가진다.
– 현재의 상태를 얻어갈 때 호출하는 메소드도 제공함
– 예제에서는, NumberGenerator 인터페이스가 해당됨

ConcreteSubject(구체적인 관찰대상자) 역할
– 구체적인 ‘관찰되는 쪽’을 나타냄
– 상태가 변하면, 등록된 Observer 역할에게 통보함
– 예제에서는, RandomNumberGenerator 클래스가 해당됨
덕성여대 컴퓨터학부
12
03. 등장 역할

Observer(관찰자) 역할
– ‘관찰하는 쪽’을 나타냄
– Subject 역할로부터 상태변화를 통보받는 역할
– 예제에서는, Observer 인터페이스가 해당됨
 통보받을 때, 관찰자의 update( ) 메소드가 호출됨

ConcreteObserver(구체적인 관찰자) 역할
– 구체적인 ‘관찰하는 쪽’을 나타냄
– 상태 변화가 관찰 대상으로부터 통보되면(즉, update 메소드가
호출되면) 그 메소드안에서 Subject 역할의 현재 상태를 얻어서
적당한 일을 수행한다.
– 예제에서는, DigitObserver와 GraphObserver 클래스가 해당됨
덕성여대 컴퓨터학부
13
03. 등장 역할
덕성여대 컴퓨터학부
14
04. 독자의 사고를 넓혀주는 힌트

여기서도 교환 가능성이 등장한다.
– RandomNumberGenerator 클래스는,
 현재 자신을 관찰하고 있는 것이 DigitObserver의 인스턴스인지
GraphObserver의 인스턴스인지 모른다.
 다만, 이들이 Observer 인터페이스를 구현하고 있다는 것만 안다.
– 한편, DigitObserver 클래스는,
 자신이 관찰하고 있는 것이 RandomNumberGenerator의 인스턴스
인지 다른 XXXXXNumberGenerator의 인스턴스인지 신경쓰지 않
는다.
 다만, 관찰대상이 NumberGenerator의 하위 클래스의 인스턴스이
고 getNumber 메소드를 가지고 있다는 것만 알고 있다.
– 관찰자와 관찰 대상을 논리적으로 분리함으로써, 각각을 쉽게
교체할 수 있다 => 확장성/교환 가능성이 높아진다.
덕성여대 컴퓨터학부
15
04. 독자의 사고를 넓혀주는 힌트

갱신을 위한 정보의 취급
– NumberGenerator는 update 메소드를 사용해서 ‘갱신되었습니다’라고
Observer에게 통지한다.
 이때, Observer 클래스의 update( )의 입력인자는 NumberGenerator 이다.
– Observer는 입력인자로 들어온 NumberGenerator를 이용하여 원하는 정보를
추출한다.
void update(NumberGenerator generator){
... ...
//generator.getNumber() 이용
... ...
}
– NumberGenerator가, 관찰자가 필요한 정보만 넘겨줄 수도 있다.
void update(int number){
... ...
//number 이용
... ...
}
덕성여대 컴퓨터학부
subject(관찰대상)이,
관찰자가 필요한 정보가
무엇인지 알아야 하는
부담을 가지고 있다.
16
04. 독자의 사고를 넓혀주는 힌트

‘관찰’하는 것이 아니고, 사실은 ‘통지’를 받는다.
– Observer의 역할이, 사실은 Subject로부터 통지가 오기를 기다리는,
수동적인 역할을 하고 있다.
– 그래서, Observer 패턴을 Publish-Subscribe 패턴이라고도 한다.
덕성여대 컴퓨터학부
17
04. 독자의 사고를 넓혀주는 힌트

Model/View/Controller(MVC)
– Smalltalk 언어에서, 하나의 데이터 모델을 여러 형태로 보여 주고자
할 때 사용되는 유명한 패턴이다.
50
D
A
C
25
B
0
A B
C
D
Subject
Observer 1
A: 40
B: 25
C: 15
D: 20
Observer 2
– Model과 View의 관계는, Observer 패턴에서 Subject와 Observer의 역
할과 서로 대응된다.
덕성여대 컴퓨터학부
18
05. 보강


JDK에서 제공되는 java.util.Observer 인터페이스와
java.util.Observable 클래스는, Observer 패턴의 일종이다.
java.util.Observer 인터페이스
public void update(Observable obj, Object arg)
관찰되는 대상

부가 정보
java.util.Observer와 java.util.Observable를 사용하기가 쉽지 않다.
– 관찰대상이 되는 클래스를 정의하기 위해서는
 java.util.Observable 클래스를 상속받아야 한다.
 그런데, 이미 Subject 역할로 생각하고 있는 클래스가 다른 클래스의 하위
클래스이면, Observable 클래스를 또 상속 받을 수가 없다. (왜냐하면, 다중
상속을 자바는 지원하지 않으므로)
– 따라서, 사용하기가 쉽지 않다.
덕성여대 컴퓨터학부
19
06. 관련 패턴

Mediator 패턴
덕성여대 컴퓨터학부
20
07. 요약

객체의 상태변화를 다른 객체에게 통지하는 Observer 패턴
덕성여대 컴퓨터학부
21
연습 문제

17-1
– 예제 프로그램에, 관찰대상으로서의
IncrementalNumberGenerator 클래스를 추가하기
 시작하는 수와 마지막 수 및 증가분을 입력받는 생성자를 가진다.
– 예: new IncrementalNumberGenerator(10, 50, 5) 인 경우
• 10부터 50까지 5씩 증가하면서 숫자 생성 (10, 15, 20, ...)
– 숫자가 만들어질 때 마다 관찰자에게 통지한다.
덕성여대 컴퓨터학부
22
startAngle
연습 문제

17-2
90
-number*360/50
(arcAngle)
0
– 예제 프로그램에 관찰자 3개를
추가함
 FrameObserver
– BorderLayout 매니저: 프레임 영역을 동서남북중앙으로 나눔
– update( ): GraphText와 GraphCanvas의 update( )를 호출함
 GraphText
– 숫자만큼의 ‘*’를 출력하는 관찰자
 GraphCanvas
– Graphics 객체의 fillArc(int x, int y, int width, int height, int startAngle,
int arcAngle)
• startAngle 부터 arcAngle 만큼 그린다
• startAngle: 0 이면 3시 위치를 의미한다. (반시계방향으로 증가)
• arcAngle: 양수이면 반시계 방향으로 그리고, 음수이면 시계방향
으로 그린다
덕성여대 컴퓨터학부
23
Homework #4: Observer 패턴 응용

예제 프로그램에 관찰자 및 관찰 대상 추가하기
– 관찰자 클래스: NamePrintObserver
 관찰 대상자로부터 통지가 올 때 마다, 관찰 대상자로부터 숫자를 얻어 그 숫자만큼의
자기 이름을 새로운 한 줄에 계속해서 출력한다.
– 예: 관찰대상자로부터 얻은 숫자가 5 인 경우
• 출력: 최승훈 최승훈 최승훈 최승훈 최승훈
– 관찰대상 클래스: PrimeNumberGenerator
 NumberGenerator의 하위 클래스로 둔다
 1부터 50 사이의 소수(prime number)를 생성한다
 생성할 때 마다 등록된 관찰자들에게 통지한다.
– Main 클래스의 main( )





PrimeNumberGenerator 의 인스턴스인 png를 생성한다.
DigitObserver와 GraphObserver 이외에 NamePrintObserver의 인스턴스를 생성한다.
png에 위의 3가지 Observer를 등록한다.
png.execute( )를 실행한다.
숙제 제출 방법: 이전 것과 똑같은 방법으로 제출함
덕성여대 컴퓨터학부
24