▣ What is Observer Pattern?
Define a one-to-many dependency between objects so that when one object changes state, all its dependent are notified and updated automatically.
옵저버 패턴은 객체간 1:多 의존 관계를 정의하여, 한 개의 객체 상태가 변경될 때, 그 객체와 의존 관계에 있는 모든 객체들이 자동으로 알림을 받고 상태를 갱신하는 패턴입니다.
옵저버 패턴은 일종의 push서비스와 비슷하다고 할 수 있습니다. 우리가 어떤 유튜브 채널을 구독했을 때, 그 유튜브에 새로운 영상이 업로드 되었는지 아닌지 계속 들어가서 확인하는 것은 번거롭겠죠? 그럴 때, 우리는 유튜브 채널을 구독한 다음 채널에 새로운 영상이 업로드되면 알림이 오도록 설정할 수 있습니다.
옵저버 패턴은 이처럼 주체(Subject)푸쉬를 받고자 하는 사용자(Observer)가 등록하고, 특정 상황이 발생하면 등록된 사용자에게 모두 알리고 자동으로 데이터가 갱신되도록 하는 패턴입니다.
위 그림에서 볼 수 있듯, Subject에서 Observer를 등록 또는 해제하고, 객체의 상태가 변경되어 옵저버에게 알려야 할 내용이 있다 notifyObservers()를 통해 옵저버에게 객체의 변경 상태를 알려줍니다.
간단한 프로그램을 통해 옵저버 패턴에 대해 좀 더 알아보겠습니다. 현재 온도, 습도, 기압과 같은 날씨 정보를 알려주는 Subject가 있고, 이 Subject에 Observer들이 등록하여 날씨 정보가 변경 될 때마다 Observer들에게 알려주는 프로그램을 만드려고 합니다.
그러면 우선 옵저버를 등록하는 메서드, 제거하는 메서드, 그리고 변경된 상태를 알려주는 메서드가 필요할 것 같고, 현재 날씨 정보를 받아 오는 메서드가 필요할 것 같습니다. 그리고 옵저버에는 변경된 날씨 정보만 알려주면 되므로 update() 메서드만 추가하면 될 것 같습니다.
// WeatherData.java
import java.util.*;
public class WeatherData implements Subject {
private ArrayList<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList<Observer>();
}
public void registerObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
if (i >= 0) {
observers.remove(i);
}
}
public void notifyObservers() {
for (int i = 0; i < observers.size(); i++) {
Observer observer = observers.get(i);
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();
}
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
}
다른 메서드들의 대한 설명은 생략하고, WeatherData의 setMeasurements() 메서드를 보시면 현재 객체의 상태가 변경(set)되면 변경된 정보들을 measurementsChanged()를 통해 Observer들에게 notify 해주는 것을 확인할 수 있습니다.
public class CurrentConditionsDisplay implements Observer, DisplayElement {
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();
}
@Override
public void display() {
System.out.println("Current conditions: "
+ temperature + "F degrees and " + humidity
+ "% humidity");
}
}
그 다음 CurrentConditionDisplay 클래스가 하나의 Observer가 됩니다. 이 클래스에서 update()를 구현하여 weatherData 객체의 상태가 변경될 때마다 display하도록 합니다.
// WeatherStation.java
import java.util.*;
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(80, 65, 1013);
weatherData.setMeasurements(82, 70, 1015);
weatherData.setMeasurements(78, 90, 1010);
}
}
위의 main()이 포함된 WeatherStation클래스를 실행하면 아래와 같이 실행되는 것을 확인할 수 있습니다.
WeatherDate의 프로그램의 전체적인 클래스 다이어그램은 아래와 같습니다.
References
[1] 조용주, 고급객체지향프로그래밍
[2] Eric Freeman, Head Frist Design Patterns
'디자인 패턴' 카테고리의 다른 글
6. Iterator Pattern (0) | 2023.11.14 |
---|---|
5. Singleton Pattern (0) | 2023.11.13 |
3. Strategy Pattern (0) | 2023.10.29 |
2-2. SOLID(S.O.L.I.D) (0) | 2023.10.18 |
2-1. SOLID(S.O.L.I.D.) (0) | 2023.10.16 |