
옵저버 패턴(Observer Pattern)은 소프트웨어 디자인 패턴 중 하나로서,
객체 간의 일대다 의존성을 정의한다.이 패턴은 한 객체의 상태가 변경될 때마다
그 객체에 종속된 모든 객체에 그 변경사항을 자동으로 알린다.
옵저버 패턴은 주로 분산 이벤트 핸들링 시스템,
모델-뷰-컨트롤러 (MVC) 아키텍처, 비동기 프로그래밍 등에서 사용된다.
옵저버 패턴이 생기기 전에는 Polling 방식을 이용해서
일정 주기로 이벤트를 감지하고 상태를 업데이트 했다.만약 확인 주기가 1시간이라고 가정해보자
1시간 안에 이벤트가 생기고 제거되면 인식할 수 없게 된다.
이러한 점을 해결하기 위해서 나온 것이 옵저버 패턴이다.
이는 관찰의 대상이 되는 객체로, Observer들이 업데이트를 받는 대상이다.
Subject는 Observer를 등록하고, 삭제하고, 알림을 보내는 메소드를 제공한다.
Subject의 상태 변화를 관찰하는 객체들이다.
모든 Observer는 업데이트 메소드를 갖는다.
Subject의 구체적인 클래스이다.
상태가 변할 때마다 Observer에게 알린다.
Observer의 구체적인 클래스로, 상태 변화를 받아 처리한다.
Observer는 Subject의 구체적인 클래스를 알 필요가 없으며,
Subject는 Observer의 구체적인 클래스에 대해 알지 못한다.
이는 Observer 인터페이스를 구현하는 새로운 클래스를 추가함으로써 이루어진다.
Observer가 많아지면, 모든 Observer에게 알림을 보내는 데 많은 시간이 소요될 수 있다.
Observer와 Subject가 서로 참조하고 있다면, 메모리 누수가 발생할 수 있다.
Observer와 Subject 인터페이스를 정의
// Observer 인터페이스
public interface Observer {
void update();
}
// Subject 인터페이스
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
WeatherData getState();
}
// WeatherData 클래스
public class WeatherData {
private float temperature;
private float humidity;
private float pressure;
// getters and setters ...
}
Observer와 Subject를 구현하는 ConcreteObserver와 ConcreteSubject를 정의
// ConcreteObserver: CurrentConditionsDisplay
public class CurrentConditionsDisplay implements Observer {
private Subject weatherStation;
public CurrentConditionsDisplay(Subject weatherStation) {
this.weatherStation = weatherStation;
weatherStation.registerObserver(this);
}
@Override
public void update() {
WeatherData data = weatherStation.getState();
System.out.println("Current conditions: " + data.getTemperature()
+ "F degrees and " + data.getHumidity() + "% humidity");
}
}
// ConcreteSubject: WeatherStation
public class WeatherStation implements Subject {
private List<Observer> observers;
private WeatherData weatherData;
public WeatherStation() {
this.observers = new ArrayList<>();
this.weatherData = new WeatherData();
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update();
}
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.weatherData.setTemperature(temperature);
this.weatherData.setHumidity(humidity);
this.weatherData.setPressure(pressure);
notifyObservers();
}
@Override
public WeatherData getState() {
return weatherData;
}
}
옵저버 패턴 테스트
public class WeatherStationSimulator {
public static void main(String[] args) {
// Subject
WeatherStation weatherStation = new WeatherStation();
// Observer
CurrentConditionsDisplay currentDisplay =
new CurrentConditionsDisplay(weatherStation);
weatherStation.setMeasurements(80, 65, 30.4f);
weatherStation.setMeasurements(82, 70, 29.2f);
}
}