옵저버 패턴(Observer Pattern)에서는 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들한테 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다(one-to-many) 의존성을 정의합니다.
옵저버 패턴에서는 주제와 옵저버가 느슨하게 결합되어 있는 객체 디자인을 제공합니다.
Design Principal 4.
서로 상호작용을 하는 객체 사이에서는 가능하면 느슨하게 결합하는 디자인을 사용해야 한다.
자바 내장 옵저버 패턴을 사용하면 푸시 방식으로 갱신할 수도 있고, 풀 방식으로도 갱신할 수 있다는 장점이 있습니다.
객체가 옵저버(Observer)가 되는 방법
Observer 인터페이스를 구현하고 addObservers를 호출합니다.
import java.util.Observable;
import java.util.Observer;
public class CurrentConditionsDisplay implements Observer, DisplayElement {
Observable observable;
private float temperature;
private float humidity;
public CurrentConditionsDisplay(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
if (o instanceof WeatherData) {
WeatherData weatherData = (WeatherData) o;
this.temperature = ((WeatherData) o).getTemperature();
this.humidity = ((WeatherData) o).getHumidity();
display();
}
}
@Override
public void display() {
System.out.println("Current condition : " + temperature + "F degress and " + humidity + "% humidity");
}
}
Observable에서 연락을 돌리는 방법
setChanged() 메소드를 호출해서 객체의 상태가 바뀌었다는 것을 알립니다.
그 다음으로 notifyObservers()
또는 notifyObservers(Object args)
를 호출합니다.
import java.util.Observable;
public class WeatherData extends Observable {
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
}
public void measurementsChanged() {
setChanged();
notifyObservers();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return humidity;
}
}
옵저버(Observer)가 연락을 받는 방법
update(Observable o, Object args)
를 통해 메소드를 구현합니다.
데이터가 수없이 변화할 때에 모든 변화에 대해서 옵저버(Observer)들에게 호출하지 않고 특정 조건일 때에만 호출을 할 수 있도록 연락을 최적화해주는 용도로 사용하게 됩니다.
옵저버(Observer)들에게 연락을 순차적으로 돌리지 않습니다.
interface가 아니고 class이기 때문에 재사용성에 있어 제약조건이 발생합니다.
Observable 인터페이스라는 것이 엇기 때문에 Observer API하고 잘 맞는 클래스를 직접 구현하는 것이 불가능합니다.
Observable 클래스의 핵심 메소드를 외부에서 호출할 수 없습니다.
Observable의 subclass에서만 setter를 호출할 수 있기 때문에 값 변경이 불가합니다.
이는 상속보다 구성
이라는 디자인 원칙에도 위배됩니다.
Java의 Observer & Observable은 Java9부터 deprecated
되었으니 참고 부탁드립니다.
Java SE 9 문서의 Observable
Deprecated.
This class and the Observer interface have been deprecated. The event model supported by Observer and Observable is quite limited, the order of notifications delivered by Observable is unspecified, and state changes are not in one-for-one correspondence with notifications. For a richer event model, consider using the java.beans package. For reliable and ordered messaging among threads, consider using one of the concurrent data structures in the java.util.concurrent package. For reactive streams style programming, see the Flow API.