헤드퍼스트 디자인패턴 2. 옵저버 패턴스터디2024. 10. 9. 09:04
Table of Contents
도입
이 장에서 소개한 디자인 원칙
- 상호작용하는 객체 사이에는 가능하면 느슨한 결합을 사용해야 한다.
옵저버 패턴
한 객체의상태가 바뀌면 그 객체에 의존하는 다른 객체에게 연락이 가고, 자동으로 내용이 갱신되는 방식으로 일대다 의존성을 정의하는 패턴
기상 모니터링 서비스 만들기
요구사항
- 기상 스테이션이 습도, 온도, 기압을 측정
- 타사에서 제공하는 WeatherData 객체를 통해 측정 값을 얻을 수 있음
- 최신 측정 값을 반영한 3가지 종류의 디스플레이(현재 상태, 예보 등)를 만들어어 함
최초 구현 코드
public void measurementsChanged() {
float temp = getTemperature();
float humidity = getHimidity();
float pressure = getPressure();
// 3가지 종류의 디스플레이
currentConditionDisplay.update(temp, humidity, pressure);
statisticsDisplay.update(temp, humidity, pressure);
forecastDisplay.update(temp, humidity, pressure);
}
이 경우, 만약 새로운 디스플레이가 추가되거나 변경이 발생하면 디스플레이 update 코드 부분을 계속해서 변경해주어야 한다.
확장성 고려
- 요구사항에 명시된 3가지 종류의 디스플레이 외에 다른 종류의 디스플레이가 언제든 추가될 수 있다는 점 고려
옵저버 패턴 적용
WeatherData(Subject)의 notifyObservers()
public void notifyObservers() {
for (Observer observer: observers) {
observer.update(temp, hum, press);
}
}
CurrentConditionDisplay(Observer)의 update()
public void update(float temp, float hum, float press) {
// 필요한 값 저장
this.temp = temp;
this.hum = hum;
// 값 수신 이후 필요한 작업 수행, 이 경우 디스플레이
display();
}
이제, 새로운 디스플레이가 추가되어도 Observer 인터페이스 구현 후, WeatherData.registerObserver() 만 수행해주면 된다.
느슨한 결합
Subject는 Observer의 구체 클래스를 모른다. 단순히 List<Observer> 를 필드로 들고 있을 뿐이다.
새로운 Observer가 추가/삭제되어도 Subject의 register/remove 메서드를 통해 언제든지 등록하고 제거할 수 있다.
또한, Subject와 Observer는 서로 독립적이며 서로가 어떤 작업을 수행하는지 알지 않아도 된다. 즉, 그 둘은 정보를 주고받지만 서로에게 영향을 받지 않도록 느슨하게 결합되어 있다.
풀 방식의 옵저버 패턴
- 현재까지의 방식은 푸시 방식으로, Subject에서 Observer로 데이터를 푸시해주는 방식.
- 이 경우, Subject가 가지고 있는 데이터가 변경되면 update() 메서드의 파라미터가 변경되어야 하므로 모든 Observer의 변경이 필요함
- update()는 (파라미터 없이) 단순 값이 변경되었다고 알리는 역할만 수행하고,
- getXxx() 메서드를 통해 Observer가 직접 값을 가져오도록 (풀) 개선하자
Observer 인터페이스
public interface Observer{
// 파라미터 없는 단순 값 변경 여부 수신 메서드
update();
}
Subject에서 Observer의 update()를 호출
public void notifyObservers() {
for (Observer observer: observers) {
// 값 자체는 전달하지 않고, 단순히 값이 변경된 사실만 알림
observer.update();
}
}
변경된 Observer의 update() 메서드
public void update() {
// Observer가 직접 값을 Pull 하는 방식, 변화에 유연하다
this.temp = weatherData.getTemp();
...
}
'스터디' 카테고리의 다른 글
헤드퍼스트 디자인패턴 3. 데코레이터 패턴 (0) | 2024.10.22 |
---|---|
헤드퍼스트 디자인패턴 1. 전략 패턴 (3) | 2024.10.03 |
@gmelon :: gmelon's greenhouse
백엔드 개발을 공부하고 있습니다.