옵서버 패턴 (Observer Pattern)
관찰자가 어떤 객체의 상태 변화를 관찰하다가 상태 변화가 있을 때마다 객체에 상속되어 있는 다른 객체들(옵서버)에게 전달하는 패턴
- 이벤트 기반 시스템 / MVC 패턴에 사용됨
- 주로 분산된 시스템 간에 이벤트를 생성 / 발행 (Publish)하고, 이를 수신(Subscribe)해야 할 때 사용
- 관찰자 : 객체의 상태 변화를 감지하는 관찰자
- 옵서버 : 객체의 상태 변화에 따라 전달되는 메서드 등을 기반으로 '추가 변화 사항'이 생기는 객체들
예제
- 옵서버 생성
// 옵서버 클래스 (base)
class Observer {
constructor(user) {
this.user = user.name;
}
notify(message) {
console.log(`User1 님이 ${this.user}님께 메시지를 보냈습니다. : ${message}`);
}
}
class Observer1 extends Observer {
constructor() {
super({ name: 'follower1' });
}
}
class Observer2 extends Observer {
constructor() {
super({ name: 'follower2' });
}
}
class Observer3 extends Observer {
constructor() {
super({ name: 'follower3' });
}
}
- 관찰 대상 클래스 생성
class Subject {
constructor() {
this.followers = []; // 객체의 변화를 감지할 옵저버 리스트
}
// 감시할 옵서버 구독
subscribe(follower) {
this.followers.push(follower);
}
// 옵서버 구독 삭제
unsubscribe(removedChild) {
this.followers = this.followers.filter(follower => follower !== removedChild);
}
// 알림
notify(message) {
for (let follower of this.followers) {
// 객체 상태 변경에 따른 옵저버의 로직 실행
follower.notify(message);
}
}
}
// User1 클래스에서 옵서버들 관리
class User1 extends Subject { }
- 옵서버 구독
// 관찰 대상 객체 생성
const user1 = new User1();
// 옵서버 객체 생성
const follower1 = new Observer1();
const follower2 = new Observer2();
const follower3 = new Observer3();
// 구독
user1.subscribe(follower1);
user1.subscribe(follower2);
user1.subscribe(follower3);
user1.notify('공지합니다.');
/** console.log
* User1 님이 follower1님께 메시지를 보냈습니다. : 공지합니다.
* User1 님이 follower2님께 메시지를 보냈습니다. : 공지합니다.
* User1 님이 follower3님께 메시지를 보냈습니다. : 공지합니다.
*/
장점
- 느슨한 결합 → 상호 의존성 최소화
- polling 방지
- polling : 상태를 주기적으로 확인하고 조건을 만족할 시 자료처리를 하는 방식
- 짧은 주기 : 부하 발생, 긴 주기 : 실시간성 떨어짐
단점
- 코드 간 연결 파악이 어려울 수 있음
- 옵저버가 복잡한 경우 성능에 문제가 발생할 수 있음
프록시 객체 이용하여 구현
# Proxy 객체
- 기본적인 동작 (속성 접근, 할당, 순회, 열거, 함수 호출 등)의 새로운 행동을 정의할 때 사용 (동작을 가로챌 수 있는 객체)
- 기존 객체의 속성이나 메소드 덮어쓸 수 있음
- 매개변수 : target, handler
# Proxy 메소드
- get() : 속성과 함수에 대한 접근을 가로챔 - target, prop, receiver
- has() : in 연산자의 사용을 가로챔
- set() : 속성에 대한 접근을 가로챔 - target, prop, val, receiver
예제
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.형규 = "커플"; // 형규가 [솔로] >> [커플] 로 변경되었습니다.
- 객체의 속성이나 메소드 변화 등을 감지하고 옵서버들에게 전달함
'STUDY > CS' 카테고리의 다른 글
[네트워크] TCP/IP 4계층 (0) | 2023.01.21 |
---|---|
[네트워크] 네트워크 토폴로지 (Network Topology) / 네트워크 분류 (2) | 2023.01.20 |
[디자인 패턴] 전략 패턴 (Strategy Pattern) / 자바스크립트 (0) | 2023.01.09 |
[디자인 패턴] 팩토리 패턴 (Factory Pattern) - 팩토리 메소드, 추상 팩토리 / 자바스크립트 (0) | 2023.01.08 |
[디자인 패턴] 싱글톤 패턴 (Singleton Pattern) / 자바스크립트 (2) | 2023.01.07 |