소프트웨어 개발자/디자인패턴

[디자인패턴] 행동 패턴 - 옵저버 패턴

yubi5050 2024. 5. 1. 17:03

행동(Behavioal) 패턴

객체들이나 클래스들 사이에 상호 작용이나 책임(역할)분배를 하는 방법에 대한 패턴. 여러 객체에 책임을 분배하고, 객체 간의 종속도 최소화 한다. 

 

주요 패턴으론 다음 사항들이 있다.

  • 옵저버(Observer) <- 이번 글에서 다룰 내용
  • 커맨드(Command) 
  • 상태(State) 
  • 전략(Strategy) 
  • 책임 연쇄(Chain_Of_Responsibility)
  • 반복자(Iterator)
  • 중재자(Mediator)
  • 반복자(Visitor)

 

옵저버 패턴 이란?

Observer 패턴은 관찰 중인 개체(주제, subject)에 이벤트가 발생시, 다른 개체들(구독자, observer)에 알리는 메커니즘으로 주제에 변화가 있으면 갱신 내용을 observer에 전달한다. 한 객체의 상태가 바뀌었을 때, 그 객체에 의존하는 다른 객체에게 연락이 가고 자동으로 내용이 갱신되는 방식은 일(주제)대다(구독자)의 의존성을 가진다고도 정의할 수 있다.

 

이러한 메커니즘을 구독 메커니즘이라고도 하며, Subject, Observer / Subscriber - Publisher 라고도 많이 지칭한다.

기술적인 예시는 메세지 큐(Message Queue) 시스템 활용시 / Event-Driven Systems 등에서 사용 될 수 있다.

 

https://refactoring.guru/images/patterns/diagrams/observer/solution1-en-2x.png

 

특징

  • Subscriber(구독자)와 Publisher(게시자)의 개념이 존재한다. 
  • Subscriber(구독자)는 Publisher(게시자)의 모든 상태, 변경 사항을 추적하고 싶어한다.

 

Publisher (게시자)

  • 게시자(Publisher)는 구독자(Subscriber) 관리 메커니즘이 존재한다.
  • 게시자(Publisher)는 구독자(Subscriber) 목록 (ex. subscribers [] ) 을 가진다.
  • 게시자(Publisher)는 구독자(Subscriber)를 add / remove / notify 처리 함수를 가지고 있다.
  • 게시자(Publisher)는 이벤트 발생시 구독자(Subscriber)에게 내용을 알려준다. (notify)

 

Subscriber (구독자)

  • 왼쪽 사진) 구독자(Subscriber)는 게시자(Publisher)에게 추가/삭제 요청을 하여 게시자(Publisher)의 목록에 보관됨
  • 오른쪽 사진) 구독자는 이벤트 발생시 게시자(Publisher)로 부터 받은 내용을 바탕으로 update() 한다.

 

좌:https://refactoring.guru/images/patterns/diagrams/observer/solution1-en-2x.png&nbsp; 우:https://refactoring.guru/images/patterns/diagrams/observer/structure-2x.png

 

추가

  • 현실에서는 1개의 Publisher 클래스 + 서로 다른(다양한 요구조건의) 구독자 클래스 존재 가능 
  • 매개변수 집합(1개)과 알림 방법(1개) 필드 등을 같이 설계하여 확장에 유연하게 함
  • 일반적으로는 Subject - Observer 용어로 표현 가능
  • 보다 확장성 측면 (다양한 타입에 대응 가능하게)의 경우 Subscriber - Publisher로 표현 가능

 

의사코드

Editor 가 이벤트를 발생 시킬시 EventManager가 관리하고 있던 listeners(구독자)들 에게 신호를 보내줌

 

https://refactoring.guru/images/patterns/diagrams/observer/example-2x.png

 

장단점

장점

  • OCP 원칙 지킴. Publisher의 코드를 변경하지 않고도 새 Subscriber 클래스 도입 가능
  • 런타임 시 관계 설정할 수 있습니다. (런타임 때 추가한다?)
  • 구독자가 동적 구독 관리 가능 (구독 등록 및 취소)
  • Observer가 자유롭게 추가되거나 생성되어도 됨. (Publisher는 리스트에 추가되거나, 추가 타입에 대한 처리만 하게될 뿐)

 

단점

  • 때론 구독자 에게 순서 보장이 안될 수 있음. (무작위)

 

다른 패턴과의 관계 

vs (행동패턴들 공통) 책임 체인(Chain of Responsibility), 명령(command), 중재자(Mediator)

  • 요청의 발신자와 수신자를 연결하는 방법들을 다룸

 

vs 책임 사슬(Chain of Responsibility)

  • 체인을 통한 수신자들의 순차적 요청 전달

 

vs 명령(Command)

  • 발신자 -> 수신자 단방향 연결

 

vs 중재자(Mediator)

  • 송/수신자 간의 직접적인 연결 없이, 중재자 개체를 통해 간접적 통신
  • 송신자 -> 중재자 -> 수신자

 

Observer

  • 송신자 -> 수신자
  • 수신자가 요청 자체에 대해 동적으로 구독 등록 및 취소 가능