-
*** 옵저버 패턴이란 주체에 종속된 관찰자들에게 주체가 나 변경됨!을 자동으로 알리는 디자인 패턴으로 분산 이벤트 처리 시스템 구현시 사용한다
코드를 구현해보자
우선 옵저버 클래스를 구현한다.
저번에 학습한대로 옵저버를 등록,해제 그리고 변경상태를 알릴 수 있또록 하는 notify가 있다.
class Observer:def __init__(self):self.subscriber = []self.msg = ""def notify(self):for sub in self.subscriber:sub.msg = self.msgdef 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 = infodef 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@abstractmethoddef register_observer(self):pass@abstractmethoddef remove_observer(self):pass@abstractmethoddef notify_observers(self):passclass Observer:@abstractmethoddef 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, abstractmethodclass Subject:__metaclass__ = ABCMeta@abstractmethoddef register_observer(self):pass@abstractmethoddef remove_observer(self):pass@abstractmethoddef notify_observers(self):passclass Observer:@abstractmethoddef update(self, temperature, humidity, pressure):pass@abstractmethoddef register_subject(self, subject):passclass weejiwon(Subject):def __init__(self):super(weejiwon, self).__init__()self._observer_list = []self.happiness = 0self.sadness = 0def 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=happinessself.sadness=sadnessself.emotionalChanged()class Emotion(Observer):def update(self, happiness,sadness): #업데이트 메서드가 실행되면 변화된 감정내용을 화면에 출력해줍니다self.happiness=happinessself.sadness=sadnessself.display()def register_subject(self, subject):self.subject = subjectself.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')'2017년 > Python' 카테고리의 다른 글
xml-rpc 다중 instance 등록방법 (0) 2017.09.16 파이썬 cmd 모듈 (0) 2017.09.15 옵저버 패턴(observer pattern) 개요 (0) 2017.09.12 파이썬의 예외처리에 대해서 (0) 2017.09.03 python에서 다른 폴더에 있는 파일 import 시키는방법 (0) 2017.07.11