이 글은 헤드퍼스트 디자인 패턴을 읽고 필자의 방식으로 이해하고 정리한 내용입니다.
개요
옵저버 패턴은 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체에게 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다(one-to-many) 의존성을 정의합니다. (헤드퍼스트 디자인 패턴, 87p)
일대다, One to Many?
개요에 적어놨듯 옵저버 패턴은 일대다 관계를 표현하는 패턴이다. 일대다 관계이다 보니 이를 이해하기 위해 알아야 둬야 할 용어가 등장하는데 바로 Subject와 Observer이다.
Subject와 Observer는 신문사와 신문사 구독자와의 관계로 설명할 수 있다. 여기서 신문사에 해당하는 개념이 Subject이고 구독자에 해당하는 개념이 Observer이다.
즉, 신문사가 소식을 발행할 때 이를 구독자에게 알리는 것과 같은 매커니즘이다.
다시 SW적으로 표현해 보자면 Subject의 상태가 변하면 이 Subject와 연결된 Observer에게 해당 정보를 알리는 것이 Obserber Pattern이다.
Observer Pattern 구조
Subject Interface
Subject를 나타내는 인터페이스이다. 이 인터페이스는 Observer를 등록하거나 탈퇴 혹은 observer에게 알림과 같이 observer에 관한 기본 동작을 정의해 놓는다.
class Subject(metaclass=ABCMeta):
@abstractmethod
def register_observer(self, observer): pass
@abstractmethod
def remove_observer(self, observer): pass
@abstractmethod
def notify_observers(self): pass
Subject Concrete Class
Subject 역할을 하는 Concreate 클래스는 항상 앞서 정의한 Subject Interface를 구현(Impl) 해야 한다. 이 구상 클래스에는 Subject Interface에서 정의한 추상 메서드 외에 추가적인 메서드가 들어갈 수 있다.
class SubjectConcreate(Subject):
def __init__(self):
self._observers = []
def register_observer(self, observer):
self._observers.append(observer)
def remove_observer(self, observer):
self._observers.remove(observer)
def notify_observers(self):
for obj in self._observers:
obj.update(1)
Observer Interface
Observer interface를 구현함으로써 Observer이 가지는 method를 나타내자.
class Observer(metaclass=ABCMeta):
@abstractmethod
def update(self, data):
pass
Observer Concreate Class
Observer Interface를 구현하여 Observer 클래스를 만든다. 즉, Observer Interface를 구현하는 클래스는 Observer가 된다.
class ObserverConcreateEx1(Observer):
def __init__(self, subject_concreate: SubjectConcreate):
subject_concreate.register_observer(self)
def update(self):
print(self.__class__.__name__, 'update method call!')
사용해 보자.
위에 선언한 observer pattern을 이루는 interface와 class들은 실제로 이 코드를 사용한다고 하면 어떻게 될까?
if __name__ == '__main__':
# subject 선언
subject_concreate = SubjectConcreate()
# observer 선언하기
observer_concreate_ex1 = ObserverConcreateEx1(subject_concreate)
# subject에 등록된 observer에게 '특정 행위' 알리기
subject_concreate.notify_observers()
요약해 보자면 다음과 같다.
- subject_concreate class를 instance 한다
- observer concreate instance화 시킨다.
- subject_concreate instance를 인자로 받아 subject_concreate class에 정의된 register_observer를 호출함으로써 observer를 등록한다.
- subject_concreate class에 정의된 특정 method로 observer에게 행위를 요청하면된다.
특징을 기억하자.
느슨한 결합!
느슨한 결합은(Loose Coupling)은 객체들이 상호작용 할 수 있지만 서로 잘 모르는 관계를 의미한다. 느슨한 결합을 사용하면 유연성이 좋아지는데 Observer Pattern은 느슨한 결합의 예제이기도 하다.
Observer Pattern의 유연성은 다음과 같다.
- Subject는 Observer가 특정 interface(observer interface)를 구현한다는 사실만 안다.
- Observer의 구상 클래스가 무엇인지 Observer가 무엇을 하는지 알 필요가 없다.
- Observer는 언제든지 새로 추가할 수 있다.
- 새로운 형식의 Observer를 추가할 때 Subject를 변경할 필요가 없다.
- Subject와 Observer는 서로 독립적이다.
Observer Pattern의 디자인 원칙
- 옵저버 패턴에서 변하는 것은 주제의 상태와 옵저버의 개수, 형식이다.
- Subject와 Observer는 상속이 아닌 구성(Composition)으로 이루어진다.
'Abstract' 카테고리의 다른 글
[Design Pattern] Strategy Pattern (0) | 2023.01.17 |
---|