취업과 기본기 튼튼/빽 투더 기본기
[디자인 패턴 12편] 행동 패턴, 옵저버(Observer)
흠시
2020. 3. 21. 16:53
1. 개념
옵저터 패턴은 하나의 관찰대상 - 여러 개의 관찰자 구조가 필요할 때 쓰는 패턴이다.
1.1. 구조
- Subject
- 관찰 대상이 되는 객체
- 자신을 관찰하는 옵저버들 리스트를 가지고 관리도 함.
- 옵저버 붙이기(attach), 떼기(detach), 알리기(notfiy) 를 가지고 있어야 함.
- Observer
- Subject 를 관찰하는 객체
- Subejct 가 notify 를 호출하면 Observer 의 update 도 호출됨.
- 즉
Observer.update()
에 관찰 대상이notify
했을 때의 할 일들을 적으면 됨.
- 즉
1.2. 장단점
- 딱히 장단점 가릴게 없는 패턴인거 같다.
- 필요에 따라 쓰는 패턴.
1.3. 활용 상황
- 관찰대상 - 관찰자의 구조를 가질 때 쓰면 된다.
- 이벤트 핸들러가 대표적인 옵저버 패턴의 예다.
- 이벤트 핸들러 : Observer
- 이벤트 : Subject
2. 구현
클라이언트는 다음과 같이 사용할 수 있다.
# 관찰 대상
subject = ConcreteSubject()
# 관찰할 옵저버를 만들고, 관찰 대상에 옵저버를 붙인다.
observer_a = ConcreteObserverA()
subject.attach(observer_a)
observer_b = ConcreteObserverB()
subject.attach(observer_b)
# 관찰 대상은 자기 할일 함. 이때 마다 전파!
subject.some_business_logic()
# 관찰 대상에서 옵저버를 뗀다.
subject.detach(observer_a)
관찰 대상인 subject
는 다음 클래스로 정의된다.
class Subject():
def __init__(self) -> None:
self._observers = []
def attach(self, observer: Observer) -> None:
self._observers.append(observer)
def detach(self, observer: Observer) -> None:
self._observers.remove(observer)
def notify(self) -> None:
for observer in self._observers:
observer.update(self)
def some_business_logic(self) -> None:
# 어떤 필요한 로직을 진행
# 이후 자신을 관찰하고 있는 옵저버들에게 알림.
self.notify()
관찰하는 대상인 observer 는 다음과 같이 정의된다.
class Observer(metaClass=ABCMeta):
@abstractmethod
def update(self, subject: Subject) -> None:
pass
class ConcreteObserverA(Observer):
def update(self, subject: Subject) -> None:
# 관찰 중인 대상을 파라미터로 받아, 해야하는 일 처리.
class ConcreteObserverB(Observer):
def update(self, subject: Subject) -> None:
# 관찰 중인 대상을 파라미터로 받아, 해야하는 일 처리.