옵저버 패턴이란 객체의 상태가 변경이 되면 객체에 의존하는 옵저버 들에게 변경된 상태를 알려주는 패턴이다.
보통 이벤트 기반 시스템에 많이 적용된다.
옵저버 패턴은 2가지로 구성이 된다.
Subject(객체이자 주체, 혼합되서 사용되는 경우) : 객체의 상태를 관리하며, subscribe등 옵저버를 등록할 수 있는 메서드가 존재한다.
observer(옵저버) : 옵저버의 상태 변화에 반응 하는 객체이다. 객체로 부터 알림을 받으면 자신의 상태를 업데이트 한다.
interface Subject {
registerObserver(observer : Observer) : void;
removeObserver(observer:Observer) : void;
notifyObservers(): void;
}
iterface Observer {
update(message: string): void;
}
class NewAgency implements Subject {
private observers: Observer[] = [];
private news: string = '';
public setNews(news: string): void {
this.news = news;
this.notifyObservers();
}
public registerObserver(observer: Observer): void {
this.observers.push(observer);
}
public removeObserver(observer: Observer): void {
this.observers = this.observers.filter(o => o !== observer);
}
public notifyObservers(): void {
this.observers.forEach((observer) => observer.update(this.news) )
}
}
// ConcreteObserver 클래스
class NewsReader implements Observer {
private name: string;
constructor(name: string) {
this.name = name;
}
public update(news: string): void {
console.log(`${this.name} received news: ${news}`);
}
}
// 사용 예시
const agency = new NewsAgency();
const reader1 = new NewsReader('희은');
const reader2 = new NewsReader('히연');
agency.registerObserver(reader1);
agency.registerObserver(reader2);
agency.setNews('TypeScript로 구현한 옵저버 패턴입니다!');
프론트에서 옵저버 패턴을 많이 볼 수 있다.
우리가 자주 쓰는 이벤트 리스너가 대표적인 예시이다.
const handler = () => {console.log('click')}
document.getElementById('btn')?.addEventListener('click', handler);
위에 코드가 있을때 Dom의 요소(btn)이 주체가 되고 등록된 콜백함수가 observer가 된다.
Subject에서 regiserter이라는 메서드가 있듯이 여기서는 addEventListner가 된다.
옵저버의 update메서드역할을 handler 함수가 하고 있다.