엘라의 개발 스케치 Note
[CS 전공지식 노트] 1.1.4 옵저버 패턴 본문
# 옵저버 패턴
더보기




? 옵저버 패턴
- 주체가 어떤 객체의 상태 변화를 관찰하다가 상태 변화가 있을 때마다 메서드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 디자인 패턴
- 주체
- 객체의 상태 변화를 보고 있는 관찰자
- 옵저버
- 이 객체의 상태 변화에 따라 전달되는 메서드 등을 기반으로 '추가 변화 사항'이 생기는 객체들
- 객체 / 주체 분리 옵저버 패턴

- 객체 - 주체 합체 옵저버 패턴

- 옵저버 패턴 활용 서비스 예시 - 트위터

- 옵저버 패턴은 주로 이벤트 기반 시스템에서 사용
- MVC 패턴에도 사용됨
- 모델(주체) -> 변경사항 update() -> 뷰(옵저버) -> 컨트롤러 등 작동
- MVC 패턴에도 사용됨

! 자바에서의 옵저버 패턴
더보기
- topic(주체이자 객체) 기반 옵저버 패턴 구현
import java.util.ArrayList;
import java.util.List;
interface Subject {
public void register(Observer obj);
public void unregister(Observer obj);
public void notifyObservers();
public Object getUpdate(Observer obj);
}
interface Observer {
public void update();
}
class Topic implements Subject {
private List<Observer> observers;
private String message;
public Topic() {
this.observers = new ArrayList<>();
this.message = "";
}
@Override
public void register(Observer obj) {
if (!observers.contains(obj)) observers.add(obj);
}
@Override
public void unregister(Observer obj) {
observers.remove(obj);
}
@Override
public void notifyObservers() {
this.observers.forEach(Observer::update);
}
@Override
public Object getUpdate(Observer obj) {
return this.message;
}
public void postMessage(String msg) {
System.out.println("Message sended to Topic: " + msg);
this.message = msg;
notifyObservers();
}
}
class TopicSubscriber implements Observer {
private String name;
private Subject topic;
public TopicSubscriber(String name, Subject topic) {
this.name = name;
this.topic = topic;
}
@Override
public void update() {
String msg = (String) topic.getUpdate(this);
System.out.println(name + ":: got message >> " + msg);
}
}
public class HelloWorld {
public static void main(String[] args) {
Topic topic = new Topic();
Observer a = new TopicSubscriber("a", topic);
Observer b = new TopicSubscriber("b", topic);
Observer c = new TopicSubscriber("c", topic);
topic.register(a);
topic.register(b);
topic.register(c);
topic.postMessage("amumu is op champion!!");
}
}
/*
Message sended to Topic: amumu is op champion!!
a:: got message >> amumu is op champion!!
b:: got message >> amumu is op champion!!
c:: got message >> amumu is op champion!!
*/
※ 자바: 상속과 구현
- 상속(extends): 일반 클래스, abstract 클래스 기반 구현
- 자식 클래스가 부모 클래스의 메서드 등을 상속받아 사용
- 자식 클래스에서 추가 및 확장 가능
- 재사용성, 중복성의 최소화
- 구현(implements): 인터페이스 기반 구현
- 부모 인터페이스(interface)를 자식 클래스에서 재정의하여 구현하는 것
- 반드시 부모 클래스의 메서드를 재정의하여 구현
! 자바스크립트에서의 옵저버 패턴
더보기
- 프록시 객체?
- 어떠한 대상의 기본적인 동작(속성 접근, 할당, 순회, 열거, 함수 호출 등)의 작업을 가로챌 수 있는 객체
- 자바스크립트에서의 프록시 객체 -> 두 개의 매개변수
- target: 프록시할 대상
- handler: target 동작을 가로채고 어떠한 동작을 할 것인지가 설정되어 있는 함수
const handler = {
get: function(target, name) {
return name === 'name' ? `${target.a} ${target.b}` : target[name]
}
}
const p = new Proxy({a: 'KUNDOL', b: 'IS AUMUMU ZANGIN'}, handler}
console.log(p.name) // KUNDOL IS AUMUMU ZANGIN
- 프록시 객체를 이용한 옵저버 패턴
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.형규 = "커플"
// 형규가 [솔로] >> [커플] 로 변경되었습니다
! Vue.js 3.0의 옵저버 패턴
더보기
- 프록시 객체를 이용한 옵저버 패턴
- Vue.js 3.0에서 ref나 reactice로 정의 -> 해당값 변경 -> 자동으로 DOM에 있는 값 변경
- DOM(Document Object Model)
- 문서 객체 모델. 웹 브라우저상의 화면을 이루고 있는 요소들
- DOM(Document Object Model)
- Vue.js 3.0에서 ref나 reactice로 정의 -> 해당값 변경 -> 자동으로 DOM에 있는 값 변경
function createReactiveObject{
target: Target,
isReadonly: boolean,
baseHandlers: ProxyHandler<any>,
collectionHandlers: ProxyHandler<any>,
proxyMap: WeakMap<Target, any> // 프록시 객체
) {
if (!isObject(target)) {
if (__DEV__) {
console.warn(`value cannot be made reactive: ${String(target)}`)
}
return target
}
// target is already a Proxy, return it.
// exception: calling readonly() on a reactive object
if (
target[ReactiveFlags.RAW] &&
!(isReadonly && target[ReactiveFlags.IS_REACTIVE])
) {
return target
}
// target already has corresponding Proxy
const existingProxy = proxyMap.get(target)
if (existingProxy) {
return existingProxy
}
// only a whitelist of value types can be observed.
const targetType = getTargetType(target)
if (targetType === targetType.INVALID) {
return target
}
const proxy = new Proxy(
target,
targetType === targetType.COLLECTION ? collectionHandlers :
baseHandlers
)
proxyMap.set(target, proxy)
return proxy
}
'CS > 면접을 위한 CS 전공지식 노트' 카테고리의 다른 글
[CS 전공지식 노트] 1.1.3 전략 패턴 (0) | 2024.03.06 |
---|---|
[CS 전공지식 노트] 1.1.2 팩토리 패턴 (0) | 2024.03.05 |
[CS 전공지식 노트] 1.1.1 싱글톤 패턴 (0) | 2024.03.04 |
[CS 전공지식 노트] 1.1 디자인 패턴 (0) | 2024.03.04 |
[CS 전공지식 노트] 1장. 디자인 패턴과 프로그래밍 패러다임 (0) | 2024.03.04 |