Observer Pattern은 특정 객체의 상태가 변화했을 때, 이와 관련한 객체들에게 변경되었음을 알리고, 정보를 적절히 수정하는 one-to-many 의존 관계를 나타낸다.
Design principle
Strive for loosely coupled designs between objects that interact
Loosely coupled designs allow us to build flexible OO systems that can handle change because they minimize
the interdependency between objects
weather station: 각 측정 장치와 연결되어 weatherData로 측정된 결과를 전달한다.
weather data: weather station으로부터 측정 결과를 가져오고, display device로 이를 전달한다.
display device: 전달받은 결과를 출력한다.
weather data는 weather station로부터 전달받은 데이터가 변경되면, 이를 각 display device 들에게 알리고 해당하는 수치들을 수정한다.
즉, weather data는 observer로서 display device들에게 변화를 감지하고 전달한다.
weatherdata는 subject 인터페이스를, 각 display 장치들은 observer와 displayElement를 참조한다.
subject는 observer 리스트를 가지고 있으며, 이를 등록, 제거하고 이들에게 변경을 공지한다.
weatherdata는 subject를 인터페이스를 구현한다.
weatherdata 에서 setMeasurements가 실행되면 가지고 있는 정보들이 변경되고. measurementsChanged가 실행된다.
measurementsChanged가 실행되면 notifyObservers가 실행되고, 가지고 있는 모든 observer들의 update 메소드가 실행된다.
특정 displayElement의 구현 객체가 생성될 때, 생성자에서 weatherdata를 인자로 받고, 해당 display의 변수로 weatherdata를 가진다.
또한, weatherdata 객체의 registerObserver 메소드로 자신을 weatherdata에 등록시킨다.
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
public interface Observer {
public void update(float temperature, float humidity, float pressure);
}
public interface DisplayElement {
public void display();
}
public class WeatherData implements Subject{
public List<Observer> observers;
public float temperature;
public float humidity;
public 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 measurementChanged() {
notifyObservers();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementChanged();
}
}
WeatherData 클래스는 Subject 인터페이스를 구현한다.
Observer 리스트를 이용하여 각 observer들을 등록, 제거한다.
setMeasuerments 메소드가 호출되면, 정보의 변화가 있는 것이므로 정보를 수정하고, measurementChanged 메소드를 호출하여 변화를 알린다.
이는 notifyObservers 메소드를 호출하고, observer 리스트에 있는 모든 observer 들의 update 메소드를 실행시킨다.
(weather station의 구현은 생략했다)
public class CurrentConditionsDisplay implements Observer, DisplayElement{
public float temperature;
public float humidity;
private WeatherData weatherData;
public CurrentConditionsDisplay(WeatherData weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("Current temperature: " + temperature + " and humidity: " + humidity);
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
}
public class AllConditionsDisplay implements Observer, DisplayElement {
public WeatherData weatherData;
public float temperature;
public float humidity;
public float pressure;
public AllConditionsDisplay(WeatherData weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("All conditions(temperature, humidity, pressure): (" +
temperature + ", " + humidity + ", " + pressure + ")");
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
display();
}
}
각 DisplayElement의 구현체들은, 생성자가 호출되면 WheaterData를 인자로 받은 후, 자신을 등록한다.
update 메소드가 호출되면 정보를 변경하고 display 메소드를 호출하여 정보들을 출력한다.
public class WeatherSimulation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay current = new CurrentConditionsDisplay(weatherData);
AllConditionsDisplay all = new AllConditionsDisplay(weatherData);
weatherData.setMeasurements(10, 10, 10);
System.out.println();
weatherData.setMeasurements(10, 20, 10);
System.out.println();
weatherData.setMeasurements(30, 30, 30);
}
}
weatherData의 setMesurements 메소드로 정보를 변경하면, 각 DisplayElement에서 변경된 정보를 출력한다.

'공부 > 디자인 패턴' 카테고리의 다른 글
| 6. Command Pattern (Head First Design Patterns) (0) | 2024.10.25 |
|---|---|
| 5. Singleton Pattern (Head First Design Patterns) (0) | 2024.10.22 |
| 4. Factory Pattern (Head First Design Patterns) (0) | 2024.10.22 |
| 3. Decorator Pattern (Head First Design Patterns) (0) | 2024.10.20 |
| 1. Strategy Pattern (Head First Design Patterns) (0) | 2024.10.20 |