Python/이것저것 파이썬

옵저버 패턴(observer pattern)

컴닥 2021. 10. 23. 12:35
반응형
# observer pattern 1

class Subscriber:
    def __init__(self, name):
        self.name = name

    def update(self, message):
        print(f'{self.name}, {message}')


class Publisher:
    def __init__(self):
        self.subscribers = set()

    def register(self, person):
        self.subscribers.add(person)

    def unregister(self, person):
        self.subscribers.remove(person)

    def dispatch(self, message):
        for subscriber in self.subscribers:
            subscriber.update(message)


p = Publisher()

kim = Subscriber('Kim')
lee = Subscriber('Lee')
jung = Subscriber('Jung')

p.register(kim)
p.register(lee)
p.register(jung)

p.dispatch('점심시간입니다.')
p.unregister(lee)
p.dispatch('퇴근시간입니다.')

 

다양한 독자 그룹을 가질 경우...

# observer pattern 2

class SubscriberGroupA:
    def __init__(self, name):
        self.name = name

    def update(self, message):
        print(f'{self.name}, {message}')


class SubscriberGroupB:
    def __init__(self, name):
        self.name = name

    def receive(self, message):
        print(f'{self.name}, {message}')


class Publisher:
    def __init__(self):
        self.subscribers = dict()

    def register(self, person, callback=None):
        if callback is None:
            callback = getattr(person, 'update')
        self.subscribers[person] = callback

    def unregister(self, person):
        del self.subscribers[person]

    def dispatch(self, message):
        for subscriber, callback in self.subscribers.items():
            callback(message)


p = Publisher()

kim = SubscriberGroupA('Kim')
lee = SubscriberGroupB('Lee')
jung = SubscriberGroupA('Jung')

p.register(kim, kim.update)
p.register(lee, lee.receive)
p.register(jung)

p.dispatch('점심시간입니다.')
p.unregister(lee)
p.dispatch('퇴근시간입니다.')

getattr(object, 'name')은 object라는 오브젝트 내부의 name이라는 멤버를 반환한다.
'문자열로 멤버를 부를 수 있다.'는 이야기
일반적으로 getattr.name 하면 될 일이기에 평소에 쓸일이 없지만, 
이놈 저놈 불러야할 때는 아주 유용하다. 

이벤트 위주로

# observer pattern 3

class Subscriber:
    def __init__(self, name):
        self.name = name

    def update(self, message):
        print(f'{self.name}, {message}')


class Publisher:
    def __init__(self, events):
        self.subscribers = {event: dict() for event in events}

    def get_subscribers(self, event):
        return self.subscribers[event]

    def register(self, event, person, callback=None):
        if callback is None:
            callback = getattr(person, 'update')
        self.get_subscribers(event)[person] = callback

    def unregister(self, event, person):
        del self.get_subscribers(event)[person]

    def dispatch(self, event, message):
        for subscriber, callback in self.get_subscribers(event).items():
            callback(message)


p = Publisher(('점심', '퇴근'))

kim = Subscriber('Kim')
lee = Subscriber('Lee')
jung = Subscriber('Jung')

p.register('점심', kim)
p.register('퇴근', lee)
p.register('점심', jung)

p.dispatch('점심', '점심시간입니다.')
p.dispatch('퇴근', '퇴근시간입니다.')

 

이런 조합도....

# observer pattern 4

class SubscriberGroupA:
    def __init__(self, name):
        self.name = name

    def update(self, message):
        print(f'{self.name}, {message}')


class SubscriberGroupB:
    def __init__(self, name):
        self.name = name

    def receive(self, message):
        print(f'{self.name}, {message}')


class Publisher:
    def __init__(self, events):
        self.subscribers = {event: dict() for event in events}

    def get_subscribers(self, event):
        return self.subscribers[event]

    def register(self, event, person, callback=None):
        if callback is None:
            callback = getattr(person, 'update')
        self.get_subscribers(event)[person] = callback

    def unregister(self, event, person):
        del self.get_subscribers(event)[person]

    def dispatch(self, event, message):
        for subscriber, callback in self.get_subscribers(event).items():
            callback(message)


p = Publisher(('점심', '퇴근'))

kim = SubscriberGroupA('Kim')
lee = SubscriberGroupB('Lee')
jung = SubscriberGroupA('Jung')

p.register('점심', kim)
p.register('퇴근', lee, lee.receive)
p.register('점심', jung)

p.dispatch('점심', '점심시간입니다.')
p.dispatch('퇴근', '퇴근시간입니다.')
반응형