행동 (4) - 옵저버(Observer) 패턴
- 객체를 관찰하다가 상태 변화가 발생하면 특정 메서드를 실행하는 패턴
- 옵저버(Observer) or 리스너(Listener)라고 부른다
- 이벤트가 발생하는 주체(Subject)는 상태 변화시 이를 전달할 옵저버 리스트를 갖고 있다
용어
- 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();
}
}
장점
- 상태를 변경하는 객체(subject)와 변경을 감지하는 객체(observer)의 관계를 느슨하게 유지할 수 있다
단점
- 복잡도가 증가한다
옵저버 패턴과 pub-sub 패턴 차이
- 메시지 송신자(Subject)가 정해진 수신자(Observer)에게 객체의 상태를 알려준다는 패턴은 동일하다 (Subject = Publisher / Observer = Subscriber)
- 옵저버 패턴은 Subject-Observer가 직접 통신하지만 pub-sub 패턴에서는 메시지 브로커나 이벤트 버스를 통한다
옵저버 패턴 | pub-sub 패턴 | ||
---|---|---|---|
의존성 | 옵저버들이 객체들을 알고 있고, 객체들은 옵저버들의 기록을 갖고 있음 | publisher와 subscriber는 서로 몰라도 되고, 메시지 큐나 브로커를 통해서 소통 | |
결합도 | 높음 | 낮음 | |
구현방식 | 대부분 동기 방식(이벤트 발생시, 객체가 모든 옵저버의 적절한 메서드 호출) | 비동기 방식(메시지 큐 사용) | |
확장성 | 1개의 app에서 구현 | 크로스 app 구현 |