소프트웨어에 대한 모든 것

[디자인패턴][Observer] 옵저버 패턴 본문

시스템 설계 및 디자인/디자인 패턴

[디자인패턴][Observer] 옵저버 패턴

앤테바 2022. 3. 24. 16:22
반응형

옵저버 패턴 정의

  • 주로 분산 이벤트 핸들링 시스템을 구현하는 데 사용
  • 발행/구독 모델로 알려져 있음
  • 객체의 상태 변화를 관찰하는 관찰자들(옵저버)의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하는 디자인 패턴
  • 어떤 객체의 상태가 변할 때 그와 연관된 객체들에게 알림을 보냄

Observer Pattern 도식화

옵저버 패턴 클래스 다이어그램

Observer 패턴 Class Diagram

옵저버 패턴 활용

날씨(온도, 습도, 압력) 데이터가 있고 날씨 데이터가 변경되면 등록한 영상 출력 기기에 정보를 업데이트 하는 시스템을 디자인 해봅시다. 날씨 데이터는 Subject에 해당하고 영상 출력기기는 옵저버(구독자)에 합니다. 

 

WehaterData는 온도, 습도, 압력 데이터를 가지고 있고, observer 리스트에 옵저버들을 관리합니다. register_observer(), unregister_observer() 함수를 통해서 관찰자를 등록/삭제 합니다. notify_observer()는 모든 옵저버에게 변경된 날씨 데이터를 알려줍니다. set_measurements() 함수를 통해서 날씨 데이터를 변경합니다.

 

Observer 클래스는 추상 클래스로 update() 함수만 있고 서브 클래스 LCDMonitorDisplay, TVDisplay에서 update()를 구현합니다.

 

from abc import ABC, abstractmethod


class Observer(ABC):
    def __init__(self):
        self.location = None

    @abstractmethod
    def update(self, temperature, humidity, pressure):
        pass


class LCDMonitorDisplay(Observer):
    def __init__(self, location):
        self.location = location

    def update(self, temperature, humidity, pressure):
        """ LCD Monitor에 날씨 데이터 출력"""
        print(f'[LCDMonitor][{self.location}] - '
              f'temperature : {temperature}, '
              f'humidity : {humidity} , '
              f'pressure : {pressure}')


class TVDisplay(Observer):
    def __init__(self, location):
        self.location = location

    def update(self, temperature, humidity, pressure):
        """ TV에 날씨 데이터 출력 """
        print(f'[TV][{self.location}] - '
              f'temperature : {temperature}, '
              f'humidity : {humidity} , '
              f'pressure : {pressure}')


class WeatherData:
    def __init__(self):
        self.temperature = None
        self.humidity = None
        self.pressure = None
        self.observers = []

    def register_observer(self, observer):
        """ 옵저버 등록 """
        self.observers.append(observer)

    def unregister_observer(self, observer):
        """ 옵저버 제거 """
        if observer in self.observers:
            self.observers.remove(observer)

    def notify_observers(self):
        """ 모든 옵저버에게 날씨 데이터 알림 """
        for observer in self.observers:
            observer.update(self.temperature, self.humidity, self.pressure)

    def set_measurements(self, temperature, humidity, pressure):
        """ 날씨 데이터를 변경하고 옵저버에게 알림 """
        self.temperature = temperature
        self.humidity = humidity
        self.pressure = pressure
        self.notify_observers()


# 관찰자 생성
lcd_display = LCDMonitorDisplay(location='빌딩 벽면')
tv_display1 = TVDisplay(location='1층 중앙 로비')
tv_display2 = TVDisplay(location='중앙 엘레베이터')

# 날씨 데이터 객체
weather_data = WeatherData()

# 관찰자 등록
weather_data.register_observer(lcd_display)
weather_data.register_observer(tv_display1)
weather_data.register_observer(tv_display2)

# 날씨 데이터 변경
weather_data.set_measurements(50, 30, 20)
weather_data.set_measurements(70, 50, 10)

출력

[LCDMonitor][빌딩 벽면] - temperature : 50, humidity : 30 , pressure : 20
[TV][1층 중앙 로비] - temperature : 50, humidity : 30 , pressure : 20
[TV][중앙 엘레베이터] - temperature : 50, humidity : 30 , pressure : 20
[LCDMonitor][빌딩 벽면] - temperature : 70, humidity : 50 , pressure : 10
[TV][1층 중앙 로비] - temperature : 70, humidity : 50 , pressure : 10
[TV][중앙 엘레베이터] - temperature : 70, humidity : 50 , pressure : 10

참고 자료

https://howtodoinjava.com/design-patterns/behavioral/observer-design-pattern/

https://aaravtech.medium.com/python-design-patterns-observer-pattern-1b9e56631f72

https://www.geeksforgeeks.org/observer-method-python-design-patterns/

반응형
Comments