덕성여대 컴퓨터학부 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