다수의 객체가 특정 객체 상태 변화를 감지하고 알림을 받는 패턴.

예제) '구독 알림' 좋아하는 유튜버의 새동영상이 올라오면 알림이 오는 것과 같음. => Subject가 자기를 구독한 모든 Observer에게 자동으로 알림을 뿌림


public class ChatServer {
private Map<String, List<String>> messages; // 주제별 메시지 목록
public void add(String subject, String message) {
// 메시지를 해당 주제 목록에 추가
}
public List<String> getMessage(String subject) {
return messages.get(subject); // 주제로 조회
}
}
public class User {
private ChatServer chatServer;
public void sendMessage(String subject, String message) {
chatServer.add(subject, message);
}
public List<String> getMessage(String subject) {
return chatServer.getMessage(subject); // 직접 가져옴
}
}
User user1 = new User(chatServer);
user1.sendMessage("디자인패턴", "이번엔 옵저버 패턴입니다.");
User user2 = new User(chatServer);
System.out.println(user2.getMessage("디자인패턴")); // ← 직접 조회
user1.sendMessage("디자인패턴", "예제 코드 보는 중..");
System.out.println(user2.getMessage("디자인패턴")); // ← 또 직접 조회
User1이 메시지를 새로 보냈는데, User2는 자기가 직접 getMessage()를 호출하지 않으면 새 메시지가 왔는지 모름
=> 실시간성 x, 자원낭비

public interface Subscriber {
void handleMessage(String message);
}
Observer 패턴의 핵심. 메시지가 오면 이 메서드로 알림
public class User implements Subscriber { // ← Subscriber 구현!
private String name;
public User(String name) {
this.name = name;
}
@Override
public void handleMessage(String message) {
System.out.println(message); // 알림 받으면 출력
}
}
public class ChatServer {
private Map<String, List<Subscriber>> subscribers = new HashMap<>();
// 1. 구독 등록
public void register(String subject, Subscriber subscriber) {
// 주제별로 구독자 목록에 추가
}
// 2. 구독 해지
public void unregister(String subject, Subscriber subscriber) {
this.subscribers.get(subject).remove(subscriber);
}
// 3. 메시지 발행 → 자동으로 모든 구독자에게 푸시
public void sendMessage(User user, String subject, String message) {
if (this.subscribers.containsKey(subject)) {
String userMessage = user.getName() + ": " + message;
this.subscribers.get(subject).forEach(s -> s.handleMessage(userMessage));
// ↑
// 구독자들에게 알아서 뿌림!
}
}
}
forEach(s -> s.handleMessage(userMessage)) 자동알림. 메시지가 들어오면 구독자 모두에게 한 번에 뿌림
ChatServer chatServer = new ChatServer();
User user1 = new User("keesun");
User user2 = new User("whiteship");
// 구독 등록
chatServer.register("오징어게임", user1);
chatServer.register("오징어게임", user2);
chatServer.register("디자인패턴", user1);
// 메시지 보내면 → 구독자들에게 자동으로 알림 감
chatServer.sendMessage(user1, "오징어게임", "이름이 일남이야..");
// → user1, user2 자동 출력
// 구독 해지하면 → 더 이상 알림 안 옴
chatServer.unregister("디자인패턴", user2);
chatServer.sendMessage(user2, "디자인패턴", "옵저버 패턴 보는 중");
// → user1만 받음 (user2는 해지됨)
User들이 미리 register()로 구독해두면, ChatServer가 메시지 올 때마다 자동으로 HandleMessage() 불러줌
장점
단점
@Component
public class MyRunner implements ApplicationRunner {
private ApplicationEventPublisher publisher;
public MyRunner(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
@Override
public void run(ApplicationArguments args) {
publisher.publishEvent(new MyEvent("hello spring event")); // 이벤트 발행!
}
}
@Component
public class MyEventListener {
@EventListener(MyEvent.class) // ← 이 어노테이션 하나면 끝
public void onApplicationEvent(MyEvent event) {
System.out.println(event.getMessage());
}
}
@EventListener : 구독 등록
회원가입 하면 환영 이메일 발송 + 통계 카운트 + 슬랙 알림