• 객체를 관찰하다가 상태 변화가 발생하면 특정 메서드를 실행하는 패턴
  • 옵저버(Observer) or 리스너(Listener)라고 부른다
  • 이벤트가 발생하는 주체(Subject)는 상태 변화시 이를 전달할 옵저버 리스트를 갖고 있다

용어

image

  • Subject : 이벤트가 발생하는 주체, 발행자(Publisher)
  • Observer : 옵저버 추상화 인터페이스
  • Concrete Observer : 상태 변화시 특정 행동을 수행하는 객체, 수신자(Subscriber)

구현

  • Observer
public interface Observer {
    public void update();
}
public class User1 implements Observer {
    private String name;

    public User1(String name) {
        this.name = name;
    }

    @Override
    public void update() {
        System.out.println(name + ": 메시지 수신!!");
    }
}

public class User2 implements Observer {
    private String name;

    public User2(String name) {
        this.name = name;
    }

    @Override
    public void update() {
        System.out.println(name + ": 메시지 수신!!");
    }
}
  • Subject
public class Subject {
    private List<Observer> observers = new ArrayList<Observer>();

    public void subscribe(Observer observer) {
        observers.add(observer);
    }

    public void unsubscribe(Observer observer) {
        observers.remove(observer);
    }

    public void notify() {
        for (Observer observer : observers) {
            observer.update();
        }
    }
}
  • Client
public class Main {

    public static void main(String[] args) {
        User1 user1 = new User1("user1");
        User2 user2 = new User2("user2");

        Subject subject = new Subject();
        subject.subscribe(user1);
        subject.subscribe(user2);

        subject.notify();
    }
}

장점

  1. 상태를 변경하는 객체(subject)와 변경을 감지하는 객체(observer)의 관계를 느슨하게 유지할 수 있다

단점

  1. 복잡도가 증가한다

옵저버 패턴과 pub-sub 패턴 차이

  • 메시지 송신자(Subject)가 정해진 수신자(Observer)에게 객체의 상태를 알려준다는 패턴은 동일하다 (Subject = Publisher / Observer = Subscriber)
  • 옵저버 패턴은 Subject-Observer가 직접 통신하지만 pub-sub 패턴에서는 메시지 브로커나 이벤트 버스를 통한다 image
옵저버 패턴 pub-sub 패턴
  의존성 옵저버들이 객체들을 알고 있고, 객체들은 옵저버들의 기록을 갖고 있음 publisher와 subscriber는 서로 몰라도 되고, 메시지 큐나 브로커를 통해서 소통
  결합도 높음 낮음
  구현방식 대부분 동기 방식(이벤트 발생시, 객체가 모든 옵저버의 적절한 메서드 호출) 비동기 방식(메시지 큐 사용)
  확장성 1개의 app에서 구현 크로스 app 구현