옵저버 패턴

2024. 9. 23. 13:37BackEnd(Java)/Design Pattern

✅ 아래 내용들에 대해서 알아보자

- 옵저버 패턴이란?
- 코드를 보면서 옵저버 패턴을 이해해보자
- 정리

 

옵저버 패턴

 옵저버 패턴은 행위패턴 중 하나로써 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체에게 연락 가고 자동으로 내용이 갱신되는 방식으로 일대다 의존성을 정의한다.  예시로 신문을 구독하는 상황으로 신문사는 신문을 제공하는 주체(Subject) 사이고 구독자는 신문을 받는 옵저버(Observers)이다.

 

 

옵저버 패턴을 실제로 적용해 볼까요?

옵저버를 구성하는 Observer 인터페이스와 주체를 구성하는 Subject 인터페이스가 구성이 됩니다.

Subject에서 데이터가 변경되면 update 메서드를 호출하여 모든 Observer들에게 데이터를 일괄 전송하는 방식을 PUSH 방식이라고 합니다. 반대로 Subject에서 필요할 때마다 데이터를 가져오는 방식을 PULL 방식이라고 합니다.

 

 

PUSH 방식의 데이터 변경

PUSH 방식의 데이터 변경

 

 

 

전체적인 다이어그램 구성도

옵저버 패턴 다이어그램

 

Subject

package com.design.designpattern.chap2;

/**
 * 주체 - 다른 객체를 잘 모르면 변화에 더 잘 대응할 수 있는 디자인 만들 수 있다.(느슨한 결합)
 */
public interface Subject {

    //옵저버 등록
    void registerObserver(DisplayObserver displayObserver);

    //옵저버 제거
    void removeObservers(DisplayObserver displayObserver);

    //옵저버들에게 변경사항 알림(푸쉬 방식)
    void notifyObservers(WeatherDto dto);
}

 

 

 

Subject 구현 클래스

package com.design.designpattern.chap2;

import java.util.ArrayList;
import java.util.List;
import lombok.Getter;

/**
 * 주체
 */
@Getter
public class WeatherData implements Subject {

    private float temperature;    //온도
    private float humidity;   //습도
    private float pressure; //기압

    List<DisplayObserver> displayObserverList = new ArrayList<>();

    //WeatherData에 갱신된 값을 가져올 때 마다 호출되는 함수
    public void measurementsChanged() {
        float temp = getTemperature();
        float hum = getHumidity();
        float press = getPressure();

        WeatherDto weatherDto = new WeatherDto(temp, hum, press);
        notifyObservers(weatherDto);
    }


    //subscribe
    @Override
    public void registerObserver(DisplayObserver displayObserver) {
        displayObserverList.add(displayObserver);
    }

    //unsubscribe
    @Override
    public void removeObservers(DisplayObserver displayObserver) {
        displayObserverList.remove(displayObserver);
    }

    @Override
    public void notifyObservers(WeatherDto dto) {
        //푸쉬 방식(subject -> observer로 데이터 전송)
        displayObserverList.forEach(w -> w.update(dto));
    }
}

 

 

Observers

package com.design.designpattern.chap2;

/**
 * 옵저버, observer
 */
public interface DisplayObserver {

    //Subject으로부터 데이터 변경시 호출되는 메서드
    void update(WeatherDto weatherDto);

}

 

 

Observers의 구현 클래스

package com.design.designpattern.chap2;

import lombok.AllArgsConstructor;

@AllArgsConstructor
public class ForecastDisplay implements DisplayObserver, DisplayElement {

    private Subject weatherData;

    @Override
    public void update(WeatherDto dto) {
        float temp = ((WeatherData) weatherData).getTemperature(); //풀방식(observer에서 subject 데이터가져옴)
        System.out.println("ForecastDisplay temp = " + dto.temp());
    }

    @Override
    public void display() {

    }
}

 

 

 

정리

  • 옵저버 패턴은 상호작용하는 객체 사이에서 느슨한 결합을 통해  유연한 구조의 디자인이 가능해집니다 😊😊
  • 옵저버 패턴은 여러 개의 주제(topic)와 메시지 유형이 있는 훨씬 복잡한 상황에서 사용하는 Pub-Sub 패턴과 친척관계입니다.(일부 유사)

 

 

참고 자료

  • 헤드 퍼스트 디자인 패턴

 

반응형

'BackEnd(Java) > Design Pattern' 카테고리의 다른 글

커맨드 패턴  (1) 2024.10.07
데코레이터 패턴  (0) 2024.09.24
전략 패턴  (2) 2022.10.10
디자인 패턴을 왜 써야할까?  (0) 2022.10.10
Builder 패턴  (0) 2022.03.30