한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들한테 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다 의존성을 정의한다.
어떠한 객체에 의존하는 다른 객체들을 Observer , 한 객체를 Subject라고 한다.
클래스 다이어그램
Subject와 Observer는 인터페이스로 구현한다.
이렇게 Subject와 Observer를 인터페이스로 구현하여 사용하면 Subject는 Observer 인터페이스만 구현하고 Obsever의 구상 클래스가 무엇인지 알 필요가 없다.
특징
옵저버는 언제든지 새로 추가할 수 있다.(Observer 인터페이스를 구현)
새로운 형식의 옵저버를 추가해도 Subject를 전혀 변경할 필요가 없다.
Subject와 옵저버는 서로 독립적으로 재사용 가능하다.
Subject나 옵저버가 바뀌어도 서로에게 영향을 미치지 않는다.
옵저버 패턴 예제
Subject, Observer
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
public interface Observer {
public void update(float temperature, float humidity, float pressure);
}
public interface DisplayElement {
public void display();
}
Subject는 Observer Interface를 등록, 삭제, 알림(notify)을 할 수 있는 기능을 가지고 있다.
Observer는 Subject가 notify 해줬을 때 업데이트하는 기능을 가지고 있다.
DisplayElement는 결괏값을 출력하기 위해 생성하였다.
ConcreteSubject
public class WeatherData implements Subject {
private List<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList<>();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
if( i >= 0){
observers.remove(i);
}
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
public void changed(){
notifyObservers();
}
public void setMeasurements(float temperature, float humidity, float pressure){
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
changed();
}
}
Subject를 구현한 클래스이다. 온도, 습도, 기압을 알려주는 클래스로 구현하였다.
Observer List와 온도, 기압, 습도를 멤버 변수로 가지고 있다.
온도, 습도, 기압을 setting 할 때 changed(); 를 호출하여 등록된 observer들에게 notify 해준다.