[디자인패턴] 옵저버 패턴 with python


Head First Design Pattern 에 소개되는 예제를 파이썬으로 구현하였습니다.


옵저버 패턴(Observer Pattern)

책에서는 옵저버 패턴을 아래와 같이 설명하고 있다.

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

예제 UML

예제 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class Subject(metaclass=ABCMeta):
def registObserver(self, obj):
pass

def removeObserver(self, obj):
pass

def notifyObservers(self):
pass

class Observer(metaclass=ABCMeta):
def update(self):
pass

class DisplayElement(metaclass=ABCMeta):
def display(self):
pass


class WeatherData(Subject):

def __init__(self):
self.observers = []

def registObserver(self, obj):
self.observers.append(obj)

def removeObserver(self, obj):
idx = self.observers.index(obj)
del self.observers[idx]

def notifyObserver(self):
for observer in self.observers:
observer.update(self.temperature, self.humidity, self.pressure)

def measurementChanged(self):
self.notifyObserver()

def setMeasurements(self, temperature, humidity, pressure):
self.temperature = temperature
self.humidity = humidity
self.pressure = pressure
self.measurementChanged()


#display
class CurrentConditionsDisplay(Observer, DisplayElement):

def __init__(self, weatherData):
self.weatherData = weatherData
self.weatherData.registObserver(self)

def update(self, temperature, humidity, pressure):
self.temperature = temperature
self.humidity = humidity
self.display()

def display(self):
print(f"Current Conditions: {self.temperature},{self.humidity}")

테스트

객체(WeatherData) 상태 변경하기

1
2
3
4
5
6
7
8
weather_data = WeatherData()

current_disaply = CurrentConditionsDisplay(weather_data)
weather_data.setMeasurements(80,65,34)
weather_data.setMeasurements(85,60,34)

#Current Conditions: 80,65
#Current Conditions: 85,60

옵저버 추가하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class ForecastDisplay(Observer, DisplayElement):

def __init__(self, weatherData):
self.weatherData = weatherData
self.weatherData.registObserver(self)

def update(self, temperature, humidity, pressure):
self.temperature = temperature
self.humidity = humidity
self.pressure = pressure
self.display()

def display(self):
print(f"Forecast tomorrow Conditions: {self.temperature+100} - {self.humidity+100} - {self.pressure+100}")

forecast_disaply = ForecastDisplay(weather_data)
weather_data.setMeasurements(80,65,34)
weather_data.setMeasurements(85,60,34)

#Current Conditions: 80,65
#Forecast tomorrow Conditions: 180 - 165 - 134
#Current Conditions: 85,60
#Forecast tomorrow Conditions: 185 - 160 - 134

옵저버 삭제하기

1
2
3
4
weather_data.removeObserver(forecast_disaply)
weather_data.setMeasurements(100,50,10)

#Current Conditions: 100,50

Comments