본문 바로가기

Abstract

[Design Pattern] Observer Pattern

728x90
반응형
이 글은 헤드퍼스트 디자인 패턴을 읽고 필자의 방식으로 이해하고 정리한 내용입니다.

 

개요

옵저버 패턴은 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체에게 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다(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()

요약해 보자면 다음과 같다.

  1. subject_concreate class를 instance 한다
  2. observer concreate instance화 시킨다.
    1. subject_concreate instance를 인자로 받아 subject_concreate class에 정의된 register_observer를 호출함으로써 observer를 등록한다.
  3. 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)으로 이루어진다.



728x90
반응형

'Abstract' 카테고리의 다른 글