기상 모니터링 애플리케이션 만들어보기
요건
기상 스테이션 (실제 기상 정보를 수집하는 물리 장비)
WeatherData 객체 (기상 스테이션으로부터 오는 정보를 추적하는 객체)
사용자에게 현재 기상 조건을 보여주는 디스플레이 객체
weatherData 가 각각 온도, 습도, 기압의 getter 메서드를 가지고 있을 때 변경때마다 디스플레이를 업데이트하는 메서드를 작성해보자.
Step1.
public class Weather Data {
// 인스턴스 변수 선언
public void measurementsChanged() {
float temp = getTemperature();
float humidity = getHumidity();
float pressure = getPressure();
currentConditionsDisplay.update(temp, humidity, pressure);
statisticsDisplay.update(temp, humidity, pressure);
forecastDisplay.update(temp, humidity, pressure);
}
}
⇒ 아래 업데이트 시, 구체적인 구현에 맞춰 코딩했으므로 프로그램을 고치지 않고는 다른 디스플레이 항목을 추가하거나 제거할 수 없다. 또, 아래 부분 바뀔 수 있는 부분이므로 캡슐화해야한다.
옵저버 패턴
신문사(subject) + 구독자(observer) = 옵저버 패턴
주제객체 → 옵저버 객체
주제에서 중요한 데이터를 관리한다. 주제 데이터가 바뀌면 옵저버에게 그 소식이 전해진다.
<aside> 💡 옵저버 패턴(Observer Pattern)은 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체에게 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다(one-to-many) 의존성을 정의한다.
</aside>
옵저버 패턴은 보통 주제 인터페이스와 옵저버 인터페이스가 들어있는 클래스 디자인으로 구현한다.
옵저버는 데이터가 변경되었을 때 주제에서 갱신해 주기를 기다리는 입장이기에 의존성을 가진다.
이런 방법을 사용하면 여러 객체가 동일한 데이터를 제어하는 방법보다 더 깔끔한 객체지향 디자인을 만들 수 있다.
느슨한 결합
객체들이 상호작용 할 수는 있지만, 서로를 잘 모르는 관계를 의미한다.
느슨한 결합을 활용하면 유연성이 아주 좋아진다.
<aside> 💡 디자인 원칙 상호작용하는 객체 사이에는 가능하면 느슨한 결합을 사용해야 한다.
</aside>
Subject Interface 구현하기
public class WeatherData implements Subject {
private List<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(Oberserver o) {
observers.remove(o);
}
public void notifyObservers() {
for(Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
public void measurementsChanged() {
notifyObservers();
}
}
디스플레이 요소 구현하기
public class CurrentConditionsDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private WeatherData weatherData;
public CurrentConditionsDisplay(WeatherData weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
public void display() {
System.out.println("현재 상태 : 온도 " + temperature + "F, 습도 " + humidity + "%");
}
}
라이브러리 속 옵저버 패턴 알아보기
JDK에 있는 자바빈(Java Bean)과 스위(Swing)
풀 방식으로 코드 바꾸기
옵저버가 필요한 데이터를 골라서 가져가도록 하는 방법이 더 좋다.