Publisher는 Subscriber interface만을 바라보고 있기 때문에 Concrete Subscribers와의 연결이 느슨해짐
Subject - Publisher / Observer - Subscriber에 대응
위 UML과의 차이점
Subject interface 를 추가적으로 두어 구체 Subject가 다형적으로 변할 수 있게 함
상태를 설정하고 알아내기 위한 state getter/setter 메서드가 있을 수도 있음
코드
// main
public class ObserverApplication {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditions currentConditions = new CurrentConditions();
weatherData.registerObserver(currentConditions);
weatherData.setMeasurements(80, 65, 30.4f);
}
}
// Subject & ConcreteSubject
public interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
public class WeatherData implements Subject {
private List<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
this.observers = new ArrayList<Observer>();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
int idx = observers.indexOf(o);
if (idx >= 0) {
observers.remove(idx);
}
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
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();
}
}
// Observer & ConcreteObserver
public interface Observer {
void update(float temp, float humidity, float pressure);
}
public class CurrentConditions implements Observer {
private float temperature;
private float humidity;
private float pressure;
@Override
public void update(float temp, float humidity, float pressure) {
this.temperature = temp;
this.humidity = humidity;
this.pressure = pressure;
display();
}
public void display() {
System.out.println("Current conditions: " + temperature + ", " + humidity + ", " + pressure);
}
}
Pros and Cons
Pros
Open/Closed Principle. You can introduce new subscriber classes without having to change the publisher's code (and vice versa if there's a publisher interface).
You can establish relations between objects at runtime.
Cons
Subscribers are notfied in random order.
자바 내장 Observerdeprecated
java.util.Observer, java.util.Observable
This class and theObserverinterface have been deprecated. The event model supported byObserverandObservableis quite limited, the order of notifications delivered byObservableis unspecified, and state changes are not in one-for-one correspondence with notifications. For a richer event model, consider using thejava.beanspackage. For reliable and ordered messaging among threads, consider using one of the concurrent data structures in thejava.util.concurrentpackage. For reactive streams style programming, see theFlowAPI.