이 글은 면접을 위한 CS 전공지식노트의 책을 읽고 학습 후 스터디 공유를 위한 글입니다.
옵저버 패턴은 주체가 어떤 객체의 상태 변화를 관찰 → 변화가 발생할 때마다 메서드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 패턴
객체와 주체가 분리되어있는 옵저버 패턴
객체와 주체가 합쳐진 옵저버 패턴
interface Subject {
register(obj: Observer): void;
notifyObservers(): void;
getUpdate(): Object;
}
interface Observer {
update(): void;
}
class Topic implements Subject {
// Topic이 주체이자 객체.
private observers: Array<Observer>;
private message: String;
constructor() {
this.observers = new Array<Observer>();
this.message = "";
}
public register(obj: Observer): void {
// 이 객체+주체에 옵저버를 등록
if (!this.observers.includes(obj)) this.observers.push(obj);
}
public notifyObservers(): void {
// 구독되어있는 옵저버들의 상태변화 시 실행할 메서드를 실행
this.observers.forEach((ele) => ele.update());
}
public getUpdate(): Object {
return this.message;
}
public updateMessage(msg: String): void{
// 이 부분이 주체의 기능에 해당하는 부분
// topic 객체의 상태인 message 프로퍼티를 변경 -> 옵저버에게 이를 알림
console.log("Message sended to Topic: " + msg);
this.message = msg;
this.notifyObservers();
}
}
class TopicSubscriber implements Observer {
private name: String;
private topic: Subject;
constructor(name: String, topic: Subject) {
this.name = name;
this.topic = topic;
}
public update(): void {
// 이후 주체에 의해 실행 됨
let msg = this.topic.getUpdate();
console.log(this.name,": got message >>", msg);
}
}
const topic = new Topic();
const observerA = new TopicSubscriber('observerA', topic);
const observerB = new TopicSubscriber('observerB', topic);
const observerC = new TopicSubscriber('observerC', topic);
topic.register(observerA);
topic.register(observerB);
topic.register(observerC);
topic.updateMessage("나는 수달이다.")
const handler = {
get: function (target, name) {
return name === "name" ? `${target.a} ${target.b}` : target[name];
}
}
const p = new Proxy({ a: "A", b: "is not B" }, handler);
console.log(p.name);
// A is not B
function createReactiveObject(target, callback) {
const proxy = new Proxy(target, {
set(obj, prop, value){
if(value !== obj[prop]){ // 상태가 변경되었음을 감지하는 부분
const prev = obj[prop]
obj[prop] = value
callback(`${prop}가 [${prev}] >> [${value}] 로 변경되었습니다`)
}
return true
}
})
return proxy
}
const a = {
"동물" : "돼지"
}
const b = createReactiveObject(a, console.log)
// 동작을 감지(이 경우 동물이라는 프로퍼티의 상태변경) 후 출력
b.동물 = "돼지"
b.동물 = "수달"
// 동물 [돼지] >> [수달] 로 변경되었습니다
ex. 주체라고 볼 수 있는 모델에서 변경사항이 생겨 update 메서드로 옵저버인 뷰에 알리고 이를 기반으로 컨트롤러 등이 작동