*** 옵저버 패턴이란 주체에 종속된 관찰자들에게 주체가 나 변경됨!을 자동으로 알리는 디자인 패턴으로 분산 이벤트 처리 시스템 구현시 사용한다
코드를 구현해보자
우선 옵저버 클래스를 구현한다.
저번에 학습한대로 옵저버를 등록,해제 그리고 변경상태를 알릴 수 있또록 하는 notify가 있다.
class Observer:
def __init__(self):
self.subscriber = []
self.msg = ""
def notify(self):
for sub in self.subscriber:
sub.msg = self.msg
def register(self, observer):
self.subscriber.append(observer)
def unregister(self, observer):
self.subscriber.remove(observer)
그리고 이 옵저버로 부터 정보를 전달 받는 친구들이 있다. 옵저버는 객체가 변경되면 이 친구들에게 정보를 전달해주는것이다.
얘네가 추가되면 이제 위의 옵저버에 있는 subcriber리스트에 추가되어서 옵저버에 종속적인 객체가될것이다.
업데이트라는 메서드를 통해 위의 옵저버 객체가 가지고 있는 msg 를 출력하도록 코드가 구현되어있다.
class subscriber:
def __init__(self):
msg = ""
def update(self):
print(self.msg)
옵저버에 의해 관찰되는 객체도 구현해준다
class Subject:
def __init__(self):
self.observer = []
def notify_observer(self, info):
for obs in self.observer:
obs.msg = info
def attach(self, observer):
self.observer.append(observer)
def dettach(self, observer):
self.observer.remove(observer)
이제 구독자 객체를 생성하고
sub1 = subscriber()
sub2 = subscriber()
sub3 = subscriber()
이 구독자들을 옵저버에 추가해준다.
ob = Observer()
ob.register(sub1)
ob.register(sub2)
ob.register(sub3)
그리고 옵저버에 의해 관찰될 객체에 옵저버를 등록시켜준다.
sub = Subject()
sub.attach(ob)
그리고서 객체에서 옵저버에게 보낼 메세지를 등록시켜준 뒤 옵저버가 자기한테 추가되어진 구독자들에게 다시 알려주고
각 구독자들의 업뎃 메서드를 수행하면
아래와 같이 결과가 나타난다.
notify msg
notify msg
notify msg
sub.notify_observer("notify msg")
ob.notify()
a.update()
b.update()
c.update()
이것만으로는 살짝 이해가 안되어서 더 찾아보았다.
이 코드는 더 직관적인것같다. 위키에서 본 다이어그램과 흡사하다
1.옵저버가 있고 이 옵저버를 구현한 각각의 옵저버들이 또 있다.
2.이 옵저버에의해 관찰되는 주제 객체를 구현한 객체가 있다
"니가바뀌는지 보는중이야!"[옵저버]=========(관찰중)========>[객체] "내가바뀌면 넌 자동으로 알아야해"
[옵저버구현N개] "바뀌면 나도알려줘!"
우선 인터페이스를 선언해준다.
class Subject:
__metaclass__=ABCMeta
@abstractmethod
def register_observer(self):
pass
@abstractmethod
def remove_observer(self):
pass
@abstractmethod
def notify_observers(self):
pass
class Observer:
@abstractmethod
def update(self):
pass
그리고 위의 인터페이스를 구현한 주제와 옵저버를 구현한다.
class ConcreteSubject(Subject):
def __init__(self):
self.state=""
self.observer_list=[]
def register_observer(self,observer):
print ('register',observer)
self.observer_list.append(observer)
def remove_observer(self,observer):
print ('remove',observer)
self.observer_list.remove(observer)
def notify_observers(self):
print 'notify msg'
class ConcreteObserver(Observer):
def update(self):
pass
이게 기본 틀이다. 인터페이스를 선언하고 후에 그 인터페이스를 구현하고!
그래서 지난번에 느슨한 결합을 언급했던것같다. 느슨한결합은 블로거분이 아주쉽게 설명해주셧는데 상호작용하긴하는데 서로 잘 모른다는것이란다.
실제로 구현해보았다. 상태가 변하면 메세지가 화면에 출력된다
from abc import ABCMeta, abstractmethod
class Subject:
__metaclass__ = ABCMeta
@abstractmethod
def register_observer(self):
pass
@abstractmethod
def remove_observer(self):
pass
@abstractmethod
def notify_observers(self):
pass
class Observer:
@abstractmethod
def update(self, temperature, humidity, pressure):
pass
@abstractmethod
def register_subject(self, subject):
pass
class weejiwon(Subject):
def __init__(self):
super(weejiwon, self).__init__()
self._observer_list = []
self.happiness = 0
self.sadness = 0
def register_observer(self, observer):
if observer in self._observer_list:
return "Already exist observer!"
self._observer_list.append(observer)
return "Success register!"
def remove_observer(self, observer):
if observer in self._observer_list:
_observer_list.remove(observer)
return "Success remove!"
return "observer does not exist."
def notify_observers(self): #옵저버에게 알리는 부분 (옵저버리스트에 있는 모든 옵저버들의 업데이트 메서드 실행)
for observer in self._observer_list:
observer.update(self.happiness,self.sadness)
def emotionalChanged(self):
self.notify_observers() #감정이 변하면 옵저버에게 알립니다.
def set_emotional(self, happiness,sadness):
self.happiness=happiness
self.sadness=sadness
self.emotionalChanged()
class Emotion(Observer):
def update(self, happiness,sadness): #업데이트 메서드가 실행되면 변화된 감정내용을 화면에 출력해줍니다
self.happiness=happiness
self.sadness=sadness
self.display()
def register_subject(self, subject):
self.subject = subject
self.subject.register_observer(self)
def display(self):
print ('weejiwon Emotion happiness:',self.happiness,' sadness:',self.sadness)
def test():
weejiwonObj = weejiwon()
EmotionObj=Emotion()
EmotionObj.register_subject(weejiwonObj)
weejiwonObj.set_emotional('good','good')
weejiwonObj.set_emotional('Not good','Not good')
weejiwonObj.set_emotional('Bad','Bad')
if __name__ == '__main__':
test()
결과
('weejiwon Emotion happiness:', 'good', ' sadness:', 'good')
('weejiwon Emotion happiness:', 'Not good', ' sadness:', 'Not good')
('weejiwon Emotion happiness:', 'Bad', ' sadness:', 'Bad')