728x90
반응형

옵저버 패턴 (observer pattern)

정의를 살펴보기 전에 클래스 다이어그램부터 살펴보자!

당연히 이해가 되지 않을 것이다. 

 

옵저버 패턴이란?

 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체에게 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다 의존성을 정의한다.

 

역시 무슨 말인지 모르겠다.

 

유튜브가 가장 좋은 예시인 것 같다.

우리가 유튜브의 쯔양의 먹방 유튜브 채널을 구독과 알림 설정을 했다고 치자. 그러면 우리는 쯔양이 실시간 방송을 하거나 컨텐츠를 올렸을 때 우리는 알림을 받게 된다. 이게 옵저버 패턴이다. 간단하지 않은가?

 

처음 봤던 클래스 다이어그램을 다시 보며 조금 더 들어가보자.

 쯔양 유튜브 채널은 Subject가 된다. 즉, 구독(registerObserver)을 하거나 구독 취소(unregisterObserver)을 하는 역할을 하고 영상이 올라왔다고 알려준다.(notifyObservers)

 구독자들(Observer)은 그저 구독을 하면 알림이 온다.(update)

ConcreteSubject, ConcreteObserver는 각각 Subject 인터페이스, Observer 인터페이스의 구현이라고 보면 된다.

그래서 저 클래스 다이어그램의 구조가 옵저버 패턴이라고 볼 수 있지.

 

---

(심화) 구현 예제

 이제는 다른 예제로 코드로 살펴보자. 이 예제는 헤드퍼스트 디자인 패턴의 예제를 가져왔다.

 

기상 데이터 중 습도, 온도, 기압의 정보를 가져와서 스마트폰 디스플레이에 띄워본다고 생각하자. 데이터 정보는 WeatherData라는 객체에 담길 것이다.

 

그럼 여기서 Subject는 WeatherData가 될 것이고, Observer는 각각의 디스플레이가 될 것이다. 클래스 다이어그램을 살펴보자.

 모든 클래스를 구현할 것은 아니다. 일단 Subject, Observer 인터페이스 부터 살펴보자.

public interface Subject {
    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObserver();
}

 

public interface Observer {
    public void update(float temperature, float humidity, float pressure);
}

간단하다. 

Subject의 역할은 Observer의 등록을 받아주거나 삭제하거나 Observer에게 알려주는 것이다.

Observer은 Subject에서 알려준 정보를 update하면 된다.

여기까지만 이해해도 옵저버 패턴에 대해서는 이해한 것이다. Subject, Observer를 구현한 것을 살펴보자.

 

public class WeatherData implements Subject{
    private List<Observer> observers;
    private float temperature;
    private float humidity;
    private float pressure;

    public WeatherData(){
        observers = new ArrayList<Observer>();
    }
    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        observers.remove(o);
    }

    @Override
    public void notifyObserver() {
        for(Observer observer:observers){
            observer.update(temperature,humidity,pressure);
        }
    }

    public void measurementsChanged(){
        notifyObserver();
    }

    public void setMeasurements(float temperature,float humidity, float pressure){
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }
}

위는 WeatherData는 Subject의 구현부 즉, ConcreteSubject이다. 쯔양 유튜브 채널이라고 생각하면 된다.

온도, 습도, 기압 데이터를 입력 받아 이를 Observer에게 알려준다.

 

 

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);
    }
    @Override
    public void update(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        display();
    }

    @Override
    public void display() {
        System.out.println("현재 상태: 온도 "+temperature +"F, 습도 "+humidity+"%");
    }
}

위 코드는 Observer의 구현부 즉, ConcreteObserver로 여러 구독자 중 한 명이라고 생각하면 된다.

그저 Subject에서 제공된 데이터를 update하면 된다.

클래스 다이어그램의 모든 것을 구현한 것은 아니다. 옵저버 패턴에 대해 이해할 정도로만 알아두자!

 

정리

 옵저버 패턴은   "한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체에게 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다 의존성을 정의한다." 이제는 이 문장이 조금 이해되었을 것이라고 생각한다.

 

 

728x90
반응형

+ Recent posts