Observer Pattern에 대해서 타이틀 줄 테스트 테스트
관찰자 패턴
Observer란 관찰(Observe)하는 사람, 관찰자를 의미한다. 이 관찰자 패턴은 관찰 대상의 상태가 변하면 관찰자에게 통지되므로 상태 변화에 따른 처리를 기술할 때 유효하다.
관찰자 패턴에 사용되는 역할
####Subject(관찰 대상자)의 역할 Subject 역할은 관찰의 대상 을 나타낸다. Subject 역할은 관찰자인 Observer 역할을 등록하는 메소드와 삭제하는 메소드를 가지고 있다. 또한 현재의 상태를 취득할 메소드도 선언되어 있다.
####ConcreteSubject(구체적인 관찰대상자)의 역할 ConcreteSubject는 구체적인 관찰의 대상 을 나타낸다. 상태가 변하면 이 것을 등록되어 있는 Observer 역할에게 전달한다.
####Observer(관찰자)의 역할 Observer는 Subject 역할로부터 상태 변화를 통보 받는 역할을 한다. 그래서 update 메소드가 존재한다.
####ConcreteObserver(구체적인 관찰)의 역할 ConcreteObserver는 구체적인 Observer의 역할을 한다. update 메소드가 호출되면 그 메소드 안에서 subject 역할이 현재의 상태를 취득한다.
예제
#####Observer 인터페이스
package io.hibrain.tutorial.designpattern.observer;
public interface Observer {
public abstract void update(NumberGenerator generator);
}
Observer 인터페이스는 관찰자 를 표현하는 인터페이스다. update 메소드는 NumberGenerator가 내용이 갱신 되었을 때 표시도 갱신하기 위해 Observer에 전달하기 위한 메소드다.
#####NumberGenerator 클래스
package io.hibrain.tutorial.designpattern.observer;
import java.util.Iterator;
import java.util.Vector;
public abstract class NumberGenerator {
private Vector observers = new Vector();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void deleteObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObservers() {
Iterator it = observers.iterator();
while (it.hasNext()) {
Observer o = (Observer)it.next();
o.update(this);
}
}
public abstract int getNumber();
public abstract void execute();
}
NumberGenerator 클래스는 수를 생성하는 추상 클래스다. 실제 수의 생성과 수를 취득하는 부분은 하위 클래스가 구현할 것을 기대해서 추상 메소드로 되어 있다. observer 필드는 NumberGenerator를 관찰하고 있는 Observer들을 보관하고 있는 필드다 . addObserver는 Observer를 추가하는 메소드이고 deleteObserver는 Observer를 삭제하는 메소드다. notifyObserver 메소드는 Observer 전원에게 ‘내용이 갱신 되었으니 알려서 갱신해달라’라고 전달하는 메소드다.
#####RandomNumberGenerator 클래스
package io.hibrain.tutorial.designpattern.observer;
import java.util.Random;
public class RandomNumberGenerator extends NumberGenerator {
private Random random = new Random();
private int number;
public int getNumber() {
return number;
}
public void execute() {
for (int i = 0; i < 20; i++) {
number = random.nextInt(50);
notifyObservers();
}
}
}
RandomNumberGenerator 클래스는 NumberGenerator의 하위 클래스로 난수를 생성한다. random 필드엔 java.util.Random 클래스의 인스턴스가 저장되고 number필드에서 현재의 난수 값이 저장 된다. getNumber 메소드는 number 필드의 값을 반환한다.
#####DigitObserver 클래스
package io.hibrain.tutorial.designpattern.observer;
public class DigitObserver implements Observer {
public void update(NumberGenerator generator ) {
System.out.println("DigiObserver:" + generator.getNumber());
try {
Thread.sleep(100);
}catch ( InterruptedException e) {
}
}
}
DigitObserver 클래스는 Observer 인터페이스를 구현하고 있는 클래스로 관찰한 수를 ‘숫자’로 표시하기 위한 클래스다. update 메소드 안에서 인수로 제공된 NumberGenerator의 getNumber 메소드를 사용해서 수를 취득하고 그것을 표시한다.
#####GraphObserver 클래스
package io.hibrain.tutorial.designpattern.observer;
public class GraphObserver implements Observer {
public void update(NumberGenerator generator) {
System.out.println("GraphObserver:");
int count = generator.getNumber();
for (int i = 0; i < count; i++) {
System.out.print("*");
}
System.out.println("");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
}
GraphObserver 클래스는 Observer 인터페이스를 구현하고 있는 클래스로 관찰한 수를 *****로 표시하기 위한 클래스다.
#####Main 클래스
package io.hibrain.tutorial.designpattern.observer;
public class HBNMain {
public static void main(String[] args) {
NumberGenerator generator = new RandomNumberGenerator();
Observer observer1 = new DigitObserver();
Observer observer2 = new GraphObserver();
generator.addObserver(observer1);
generator.addObserver(observer2);
generator.execute();
}
}
Main 클래스에서는 RandomNumberGenerator의 인스턴스를 1개, 관찰자를 2개 만든다. 한 관찰자에서는 숫자로 표시하는 DigitObserver의 인스턴스를, 다른 관찰자에서는 GraphObserver의 인스턴스를 만들고 addObserver 메소드를 사용하여 관찰자를 등록 후 generator.execute를 사용하여 수를 생성한다.
참고자료
Java 언어로 배우는 디자인 패턴, Yuki Hiroshi ,2001