옵저버 패턴
- 옵저버 패턴
비유 : 신문사와 정기구독자
중요한 일이 일어났을 때 객체들에게 새소식을 알려준다.
객체들은 계속해서 정보를 받을지 여부를 실행중에 결정할 수 있다.
한 객체(주제)의 상태가 바뀌면 그 객체에 의존하는 다른 객체들(옵저버)한테 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다 의존성을 정의한다.
데이터의 주인은 주제
ex. 기상 모니터링 애플리케이션
3가지 구성 요소 : 기상 스테이션(실제 기상 정보를 수집하는 장비)
WeatherData 객체(기상 스테이션으로부터 오는 데이터를 추적하는 객체)
현재 기상 조건을 보여주는 기상 디스플레이
- 구현
Subject의 인터페이스(registerObserver, removeObserver, notifyObservers),
Observer의 인터페이스(update)
각각의 구상 클래스
옵저버들이 모두 똑같은 인터페이스를 구현해야만 주제에서 데이터를 보내줄 수 있다.
- 옵저버 패턴의 특징
1) 바뀌는 부분을 찾아내서 바뀌지 않는 부분으로부터 분리시킨다.
옵저버 패턴에서 변하는 것은 주제의 상태와 옵저버의 개수, 형식이다.
옵저버 패턴에서는 주제를 바꾸지 않고도 주제의 상태에 의존하는 객체들을 바꿀 수 있다. 나중에 바뀔 것에 대비할 수 있다.
2) 특정 구현이 아닌 인터페이스에 맞춰서 프로그래밍한다.
Subject와 Observer에서 모두 인터페이스를 사용한다.
Subject에서는 Subject 인터페이스를 통해서 Observer 인터페이스를 구현하는 객체들의 등록/탈퇴를 관리하고 그런 객체들한테 연락을 돌린다. 결합을 느슨하게 만든다.
3) 구성을 활용
주제와 옵저버 사이의 관계는 상속이 아니라 구성에 의해서 이루어진다.
실행중에 구성된다.
- 느슨한 결합(Loose coupling)
주제와 옵저버가 느슨하게 결합되어 있다.
그 둘이 상호작용을 하긴 하지만 서로에 대해 서로 잘 모른다.
주제가 옵저버에 대해 아는 것은 옵저버가 특정 인터페이스를 구현한다는 것 뿐
- ex.
package observer;
import java.util.ArrayList;
public class WeatherData implements Subject {
private ArrayList observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList();
}
public void registerObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
if (i >= 0) {
observers.remove(o);
}
}
public void notifyObservers() {
for (int i=0;i<observers.size();i++) {
Observer observer = (Observer) observers.get(i);
observer.update(temperature, humidity, pressure);
}
}
public void measurementsChanged() {
notifyObservers();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature= temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
package observer;
public class CurrentConditionsDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
public void display() {
System.out.println("Current conditions : " + temperature
+ "F degrees and " + humidity + "% humidity");
}
}
출처 : HeadFirst Design Patterns