- 주체가 어떤 객체의 변화를 관찰하다가 변화가 일어났을 때, 메서드 등을 통해 주체를 바라본 옵저버들에게 변화를 알려주는 패턴
- SNS를 예시로, 내가 어떤 사람을 팔로우하고 있을 때, 팔로우한 사람이 피드를 올리면 나에게 피드가 확인되는 스텝으로 이해하면 될 듯
예시
- 아래는 Javascript로 옵저버를 구현한 예시
var observer = {
handlers: {}, // 각 모듈에 등록할 핸들러들을 담아줌
// 상태 변화가 발생할때 실행할 이벤트들을 등록
// context도 같이 받아 내부에서 this를 적절히 사용할수 있게 실행
register: function(eventName, handler, context) {
let handlerArray = this.handlers[eventName];
if (handlerArray === "undefined") {
handlerArray = this.handlers[eventName] = [];
}
// handlers 배열에 관리
handlerArray.push({
handler: handler,
context: context
});
}
// 등록한 핸들러를 해제해줌
unregister: function(eventName, handler, context) {
// 걍 handlerArray에서 splice해주면 되는거라 코드는 적지 않겠음
}
// 특정 상태가 변화되었을때 이벤트들을 알림해줄 함수
notify: function(eventName, data) {
const handlerArray = this.handlers[eventName];
for (let i = 0; i < handlerArray.length; i++) {
let currentHandler = handlerArray[i];
// 핸들러를 바로 호출하지 않고 call을 쓰는데 위 register에 등록한
// context 객체를 내부에서 this로 사용하게끔 전달하기 위함
currentHandler["handler"].call(currentHandler["context"], data);
}
}
};
// 여기에 사장, 팀장, 개발자가 있다
let boss = new Person();
let manager = new Person();
let programmer = new Person();
// 사장님이 말할때 옵저버의 이벤트를 발생시키도록 넣고
boss.speak = function(comment) {
alert(comment);
observer.notify("bossSpeak", comment);
}
// 팀장님은 사장님의 얘기를 담아둔다
// 옵저버로 등록해 사장님이 언제든지 얘기할때 담아둘수 있도록 구현한 것
// 옵저버 알림이 그냥 manager.listen으로 수행하게 했다면 this가 manager인지 모름
// 그래서 알림 notify에선 context도 같이 받아서 call하여 manager라는걸 알게 해줌
// 이 부분이 context 내부에서 this를 활용하기 위함이다, 이런건 참 까다롭다
manager.listen = function(comment) {
this.bossComment = comment;
}
observer.register("bossSpeak", manager.listen, manager);
// 개발자는.. 그냥 말씀따윈 무시하도록 구현
programmer.drop = function(comment) {
return comment;
}
observer.register("bossSpeak", programmer.drop, programmer);
// boss가 이제 말하기 시작하면 아래처럼 매니저와 프로그래머에게도 알림이 가서 작동
boss.speak("Blah Blah Blah...");
// manager.listen("Blah Blah Blah...");
// programmer.drop("Blah Blah Blah...");
- 위 코드 예시론 직접 구현을 하였지만, Proxy 객체를 두어 특정 객체 변화를 감지하여 미리 설정한 옵저버들에게 전달하도록 구현할 수도 있다
- 해당 패턴의 이점은 옵저버들의, 모듈의 연관성을 높이면서도 의존성은 제거할 수 있다
- 위 예시로 boss가 얘기할 때, manager나 programmer에게 의존 사실은 있지만 옵저버를 통해 직접 의존성은 제거하고 연관성을 유지할 수 있게 되는 것
- 초기 프로젝트부터 개발을 하다 보면 규모가 자연스레 커지게 되는데, 이 때 여러 모듈과의 의존성이 생길 수 있으므로 옵저버 패턴을 통해 의존성을 조금씩 줄여줄수 도 있다