Observer Pattern
Overview

When to use
특정 객체의 상태가 변경될 때 다른 객체에게 알림을 전달해야 할 때
- 버튼 클릭시 Display 업데이트
 - 이벤트 발생시 Display 업데이트
 
Why to use
How to use
Subject (주제) 와 Observer (관찰자)로 구성한다. \ 예제의 Display 는 보통 옵저버 패턴이 Button + Event Listener (옵져버) 에서 자주 쓰이고 \ 이벤트 리스너가 화면 변경 역할도 한다고 가정해서 추가한 인터페이스다.
Interface
- Subject
 - Observer
 - Display
 
public interface Subject {
  void registerObserver(Observer observer);
  void unregisterObserver(Observer observer);
  void notifyToAllObservers();
}
public interface Observer {
  void onUpdate();
}
public interface Display {
  void display();
}
Concrete Class
- ConditionDisplay
 - Statistics
 
@Slf4j
@ToString
public class CurrentConditionDisplay implements Observer, Display {
  private final WeatherData weatherData;
  private double currentTemperature;
  private double currentHumidity;
  public CurrentConditionDisplay(WeatherData weatherData) {
    this.weatherData = weatherData;
    this.currentTemperature = weatherData.getTemperature();
    this.currentHumidity = weatherData.getHumidity();
    weatherData.registerObserver(this);
  }
  @Override
  public void display() {
    log.info(this.toString());
  }
  @Override
  public void onUpdate() {
    if (weatherData.getTemperature() == this.currentTemperature &&
      weatherData.getHumidity() == this.currentHumidity) {
      return;
    }
    this.currentTemperature = this.weatherData.getTemperature();
    this.currentHumidity = this.weatherData.getHumidity();
    this.display();
  }
}
@Slf4j
class StatisticsDisplay implements Display, Observer {
  // It's not required to removeObserver from WeatherData since display always exist with the weatherData.
  private final WeatherData weatherData;
  private double totalTemperature;
  private double maxTemperature;
  private double minTemperature;
  private double avgTemperature;
  private int count = 0;
  public StatisticsDisplay(WeatherData weatherData) {
    this.weatherData = weatherData;
    weatherData.registerObserver(this);
  }
  @Override
  public void display() {
    log.info("Max temperature: {}, Avg temperature: {}, Min temperature: {}", this.maxTemperature, this.avgTemperature, this.minTemperature);
  }
  @Override
  public void onUpdate() {
    this.totalTemperature += weatherData.getTemperature();
    this.maxTemperature = Math.max(maxTemperature, weatherData.getTemperature());
    this.minTemperature = Math.min(minTemperature, weatherData.getTemperature());
    this.count++;
    this.avgTemperature = totalTemperature / count;
    this.display();
  }
}
Push 방식
Subject 가 Observer 에게 데이터를 직접 전달한다.
Polling 방식
이벤트 발생시 Observer 가 필요한 데이터를 Subject 에게 요청한다.
팁
📝 Polling 방식을 사용하라. Subject 변경에 유연하고, 필요한 데이터만 접근한다.
Pros and Cons
Pros
- 동기식으로 구현하면 디버깅이 쉽다.
 
Cons
- Pub/Sub 패턴에 비해 객체간 의존성 강결합이 발생한다. 
Observer - Subject 간의 의존성이 강하다.