Observer Pattern
객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴
옵서버 observer 관찰자(참관인) 회의 등에서 정식 멤버로는 인정되지 않으나, 특별히 출석이 허용된 사람
특징
마트와(Subject) 손님(Observer)로 비유시, 마트에 상품이 들어오면 손님에게 알림이 가는 형식
- 푸쉬 시스템 기반 주체(Subject)가 상태 변화를 감지하면 등록된 모든 관찰자(Observer)에게 자동으로 변화 내용을 푸쉬. 관찰자는 별도의 요청을 하지 않아도 주체로부터 변화를 즉시 전달 받음
- 클래스의 의존성이 낮아 느슨한 결합을 유지. 인터페이스와 추상 클래스를 통해 상호작용
- 한정된 시간, 특정 케이스에 다른 객체를 관찰할 때 사용
- 구현방식
- notifyObserver 한 개의 관찰 대상자(Subject)와 여러 관찰자(Observer A, B, C)로 일 대 다 관계 구성
- update 관찰 대상의 상태가 바뀌면 변경사항을 옵저버에 통보
- 통보받은 Observer는 값을 바꾸거나 삭제 등 대응. Observer는 언제든 Sub 그룹에 추가 및 삭제될 수 있다
예시 코드
sub
SubListener
인터페이스
관찰자 역 인터페이스로,
update
메서드 정의Pub
클래스가 해당 인터페이스 타입 이용하여 관찰자 목록 관리sub1, 2
클래스SubListener
인터페이스를 구현한 구독자 역.update
메서드를 통해 주체(Subject)로부터 알림을 수신
pub
- 구독자 관리 및 알림 메서드
Pub
클래스의add
와remove
메서드는 구독자 목록(subList
)을 관리
PubListener
인터페이스notifyChange
: 주체인Pub
의 상태 변화가 발생 시, 각 구독자(관찰자)에게 알림 전달sub.update(msg);
는SubListener
인터페이스의update
메서드를 호출로, 각 구독자가update
메서드를 통해 메시지를 받음
package ch07;
import ch07.pub.Pub;
import ch07.pub.PubListener;
import ch07.sub.Sub1;
import ch07.sub.Sub2;
import ch07.sub.SubListener;
// 옵저버 패턴 -> 콜(구독)백(나중에)
public class App {
public static void main(String[] args) {
// 1. 객체 생성 init -최초 등록 시, 모든 필요 객체 등록
PubListener pub = new Pub();
SubListener sub1 = new Sub1();
SubListener sub2 = new Sub2();
// 2. 구독하기
pub.add(sub1);
pub.add(sub2);
// 3. 상품 들어옴(가정)
// 4. notifyChange 호출 -상품이 들어왔으니 호출
pub.notifyChange("상품 들어옴");
}
}
package ch07.pub;
import ch07.sub.SubListener;
public interface PubListener { // 예) pub 마트, sub 손님
void add(SubListener sub); // 서버 컬렉션 등록 -Sub 구현체 가짐
void remove(SubListener sub); // 서버 컬렉션 제거 -Sub에서 어떤 객체인지 받기
void notifyChange(String msg); // 변화 알림 -상품 입고 시 실행
}
package ch07.pub;
import ch07.sub.SubListener;
import java.util.ArrayList;
import java.util.List;
public class Pub implements PubListener{
// 구독자 명단
List<SubListener> subList = new ArrayList<>();
@Override
public void add(SubListener sub) {
subList.add(sub);
}
@Override
public void remove(SubListener sub) {
subList.remove(sub);
}
// 책임: 물건이 들어오면, 구독자들에게 알림을 보냄
@Override
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);
}
}
}
package ch07.sub;
public class Sub1 implements SubListener {
@Override
public void update(String msg) {
System.out.println("Sub1이 받은 알림: " + msg);
}
}
package ch07.sub;
public class Sub2 implements SubListener {
@Override
public void update(String msg) {
System.out.println("Sub2가 받은 알림: " + msg);
}
}
package ch07.sub;
public interface SubListener {
void update(String msg);
}
출력

Share article