
옵저버 패턴(Observer Pattern)은 한 객체의 상태가 변경될 때, 이를 의존하는 객체들에게 자동으로 알림을 보내는 패턴입니다. 발행(Publisher) - 구독(Subscriber) 모델로도 알려져 있으며, 한 객체(subject)의 상태 변화가 여러 객체(observer)에게 영향을 미쳐야 하는 경우 유용합니다.
일반적으로 한 객체의 상태가 변할 때, 여러 객체에서 이를 감지해야 한다면 직접적으로 여러 객체를 참조해야 합니다. 하지만 이렇게 하면 결합도가 높아지고 유지보수가 어려워지는 문제가 발생합니다.
옵저버 패턴을 적용하면 느슨한 결합(Loose Coupling) 을 유지하면서도 객체 간의 관계를 효과적으로 관리할 수 있습니다. 즉, Subject는 Observer가 어떤 객체인지 알 필요가 없으며, 단순히 Observer 인터페이스를 통해 상태 변경을 알리기만 하면 됩니다.
+-------------------+ +------------------+
| Subject |<------| Observer |
+-------------------+ +------------------+
| + register() | | + update() |
| + remove() | +------------------+
| + notify() |
+-------------------+
|
v
+----------------------+ +----------------------+
| ConcreteSubject | | ConcreteObserver |
+----------------------+ +----------------------+
| - state | | - subject |
| + getState() | | + update() |
| + setState() | +----------------------+
+----------------------+
// Subject 인터페이스 (발행자)
public interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
// Observer 인터페이스 (구독자)
public interface Observer {
void update(float temperature, float humidity, float pressure);
}
import java.util.ArrayList;
import java.util.List;
// 구체적인 Subject (WeatherData)
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) {
observers.remove(o);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
notifyObservers();
}
}
// 구체적인 Observer (현재 상태 디스플레이)
public class CurrentConditionsDisplay implements Observer {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
public void display() {
System.out.println("현재 상태: 온도 " + temperature + "C, 습도 " + humidity + "%");
}
}
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(25.5f, 65.0f, 1013.1f);
weatherData.setMeasurements(27.0f, 70.0f, 1012.5f);
}
}
현재 상태: 온도 25.5C, 습도 65.0%
현재 상태: 온도 27.0C, 습도 70.0%
옵저버 패턴은 이벤트 기반 프로그래밍에서 자주 사용되는 강력한 디자인 패턴입니다. 특히 GUI 프로그래밍, 실시간 데이터 스트리밍, 메시지 브로커 시스템 등에서 효과적입니다. 하지만 옵저버 등록 해제 및 성능을 고려하여 신중하게 설계하는 것이 중요합니다.