티스토리 뷰

반응형

옵저버 패턴(Observer Pattern)

 한 객체의 상태가 바뀌면 그 객체를 관찰(구독)하고 있던 다른 객체에게 연락이 가고 자동으로 내용이 갱신되는 패턴입니다.

옵저버 패턴을 사용해 일대다(one-to-many)의 의존성을 정의할 수 있습니다.

 

ex) java.swing 라이브러리: AbstractButton의 코드에서 옵저버 패턴의 필수품인 리스너들을 잔뜩 발견할 수 있습니다!



옵저버 패턴의 구조와 작동 방식

https://refactoring.guru/ko/design-patterns/observer

 

1. Publisher(출판사) 객체에서 중요한 데이터를 관리합니다.

2. Publisher의 데이터가 바뀌면 Publisher를 구독하고 있는 Subscriber(구독자) 객체들에게 바뀐 데이터의 내용이 전달됩니다.

3. Subscriber 객체들은 Subscriber 인터페이스의 구현체로 모두 같은 단일 메서드를 통해 갱신 내용을 전달받을 수 있습니다.

4. Subscriber가 아닌 객체는 Publisher의 데이터가 바뀌어도 아무 연락도 받지 않습니다.

 

 

느슨한 결합 ? (Loose Coupling)

옵저버 패턴은 느슨한 결합을 사용한 훌륭한 예시입니다.

느슨한 결합은 객체들이 상호작용할 수는 있지만, 서로를 잘 모르는 관계를 의미합니다.

느슨한 결합을 사용하면 코드의 유연성이 좋아진다는 장점이 있습니다.

 

  • Publisher는 Subscriber 클래스들이 Subscriber 인터페이스를 구현한다는 사실만 안다.
  • 새로운 Subscriber 구현 클래스는 언제든지 새로 추가할 수 있다.
  • 새로운 형식의 Subscriber를 추가해도 Publisher는 변경할 필요가 전혀 없다.
  • Subscriber와 Publisher는 서로 독립적으로 재사용할 수 있다.
  • Subscriber나 Publisher가 달라져도 서로에게 영향을 미치지 않는다.

 

 

책에서 제시하는 옵저버 패턴의 사용 예시

문제 상황

 WeatherData 객체는 현재 기상 조건(온도, 습도, 기압)을 추적한다. 이 객체를 바탕으로 3개의 항목을 화면에 표시하는 애플리케이션을 만들도록 한다. 3개의 항목은 각각 현재 조건, 기상 통계, 간단한 기상 예보이며, 이 항목들은 모두 WeatherData 객체에서 최신 측정치를 수집할 때마다 실시간으로 갱신된다. 다른 개발자가 또 다른 화면을 만들어 바로 넣을 수 있도록 확장 가능해야 한다.

 

 

주어진 WeatherData 클래스 코드

public class WeatherData {
    ...
    
    public float getTemperature()
    
    public float getHumidity()
    
    public float getPressure()
	
    // 정보가 갱신될 때마다 이 메소드가 호출됩니다.
    public void measurementsChanged()
}

 

 

해결 방법

Publisher(또는 Subject) 인터페이스 구현 (가상 스테이션)

// 주제 인터페이스
public interface Subject {
    // 옵저버 등록
    public void registerObserver(Observer o);
    
    // 옵저버 제거
    public void removeObserver(Observer o);
    
    // 주제의 상태가 변경되었을 때 모든 옵저버에게 변경 내용을 알리기 위해 호출
    public void notifyObservers();
}

// 옵저버 인터페이스
public interface Observer {
    public void update();
}

// 화면 인터페이스
public interface DisplayElement {
    // 디스플레이 항목을 화면에 표시해야 할 때 호출
    public void display();
}

 

 

Subject 인터페이스 구현 - WeatherData 클래스

public class WeatherData implements Subject {
    private List<Observers> 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) {
        observers.remove(o);
    }

    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }

    public void measurementsChanged() {
        notifyObservers();
    }
    
    ...
}

 

 

많은 옵저버 구현 클래스 중 CurrentConditionDiplay 요소 구현

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() {
        this.temperature = weatherData.getTemperature();
        this.humidity = weatherData.getHumidity();
        display();
    }
    
    public void display() { ... }
}

 

 

 

참조:

 

헤드 퍼스트 디자인 패턴(개정판)

유지관리가 편리한 객체지향 소프트웨어 만들기! “『헤드 퍼스트 디자인 패턴(개정판)』 한 권이면 충분합니다!”

m.hanbit.co.kr

 

반응형