옵저버 패턴

김인범's avatar
Nov 14, 2024
옵저버 패턴
한 객체의 상태가 변경되었을 때, 그 객체에 의존하는 다른 객체들에게 자동으로 알람이 가도록 설계하는 행동 디자인 패턴. (발행-구독 모델)
 
주로 일대다 관계에서 사용된다.
 
어떤 객체의 상태 변화가 여러 객체에 영향을 미칠 때 유용합니다.
 

구성요소

  1. 주제
상태변화 감지, 옵저버들을 관리하는 역할입니다. 상태가 변경되면 → 옵저버들에게 알림을 전송
  1. 옵저버
상태 변화를 구독하여 알림을 받는 객체입니다.
  1. 구체적인 주제
주제의 상태와 구독된 옵저버 목록을 관리하는 구체적인 클래스입니다.
  1. 구체적인 옵저버
구체적인 행동을 정의하는 옵저버, 상태 변경 시 특정 동작을 수행합니다.
 

동작방식

notion image
 

**폴링 방식(Polling)

하나의 프로그램이 충돌 회피 or 동기화 처리 등을 다른 장치의 상태를 주기적으로 검사하여 일정 조건을 만족할 때 송수신 등의 자료처리를 하는 방식
 

장점과 단점

장점

  1. 느슨한 결합
주제와 옵저버의 결합이 느슨하여, 서로의 존재에 의존하지 않고 독립적으로 작동가능
  1. 확장성
주제 코드의 수정없이 기능 확장 가능
  1. 자동 알림
상태 변화 발생 시. 주제가 자동으로 옵저버들에게 알림을 전송 ⇒ 일관성 유지 가능

단점

  1. 예측하기 어려운 흐름
옵저버가 많아지면, 주제의 상태 변화가 여러 객체에 동시에 영향을 미쳐 코드 흐름을
예측하기 어려울 수 있습니다.
  1. 성능 문제
옵저버가 많거나 알림 빈도가 잦을 경우 성능에 영향을 줍니다.
 

예시 코드

pub (주제)

public class Pub { public String value = null; // 상품 들여오는 역할 public void income(){ value = "바나나"; } //1. 구독자 명단 List<SubListener> subList = new ArrayList<>(); public void add(SubListener sub) { subList.add(sub); } public void notifyChange(String msg) { // 5초 잠자기 for (int i = 1; i < 6; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("."); } //구독자들에게 알림주기 for(SubListener sub: subList){ sub.update(msg); } } }
 

sub (옵저버)

public interface SubListener { void update(String msg); } public class Sub1 implements SubListener{ @Override public void update(String msg) { System.out.println("sub1이 받은 알림:" + msg); //무엇을 해야할지? } } public class Sub2 implements SubListener{ @Override public void update(String msg) { System.out.println("sub2가 받은 알림:" + msg); //무엇을 해야할지? } }
 

Main

public class App { public static void main(String[] args) { // 1. 객체 생성 init Pub pub = new Pub(); SubListener s1 = new Sub1(); SubListener s2 = new Sub2(); // 구독하기 pub.add(s1); pub.add(s2); // 2. 상품이 들어옴 pub.income(); // 3. 알림 작동 if(pub.value == null) { System.out.println("상품 미입고...."); } else { pub.notifyChange(pub.value + " 입고됨"); } } }
 
pub이라는 주제를 sub 객체가 pub.add( );를 통해 구독하게 되었습니다. 이후 pub.income( );을 통해 “바나나”가 value 값에 들어가 상태가 변화하였습니다.
이제 pub 의 상태가 변화하였으니, pub을 구독하고 있는 옵저버(sub)객체들에게 알림을 보내기 위해 .notifyChange 를 사용해 옵저버 객체들에게 알림이 가게 됩니다.
Share article

taker