"JavaScript Design Pattern" 포스팅은 ChatGPT에게 "Essential design patterns for JavaScript developers to learn"로 질문한 뒤 나온 내용에 대해 정리하는 포스팅입니다.
1. 옵저버 패턴(Observer Pattern)
옵저버 패턴은 주체(Subject)로 불리는 객체가 옵저버라고 하는 종속 객체의 목록을 유지 관리하고, 일반적으로 메서드 중 하나를 호출하여 상태 변경을 자동으로 알리는 디자인 패턴이다.
옵저버 패턴은 객체 간의 느슨한 결합을 허용하여 서로의 구현에 대해 세부 사항을 알 필요 없이 상호 작용할 수 있다.
옵저버 패턴은 주체와 주체의 옵저버 간의 일대다 관계를 정의한다. 주체가 변경되면 모든 옵저버에게 알림이 전달되고 자동으로 업데이트된다.
옵저버 패턴은 게시/구독 패턴(Publish/Subscribe Pattern)으로도 알려져 있는데, 게시자가 메시지를 수신하는 데 관심을 표명한 모든 구독자에게 메시지를 브로드캐스트 하는 메시징 시스템에서 종종 사용되기 때문이다.
옵저버 패턴은 객체의 상태가 자주 변경되고 다른 객체가 그에 따라 반응해야 하는 이벤트 중심 아키텍처나 애플리케이션에서 자주 사용된다.
몇 가지 일반적인 사용 사례로는 사용자 상호작용에 따른 UI 업데이트, 실시간 데이터 스트리밍, 네트워크 통신 등이 있다.
JavaScript에서 옵저버 패턴은 다음과 같은 여러 기술을 사용하여 구현할 수 있다.
- 콜백 함수: 대상 객체는 대상의 상태가 변경될 때마다 호출되는 콜백 함수 목록을 유지 관리한다.
- 이벤트 리스너: 주체 객체가 이벤트를 방출하고, 옵저버 객체는 해당 이벤트를 수신하고 그에 따라 응답한다.
- Promises: 주체 객체는 주체의 상태가 변경되면 resolve 되는 promise를 반환한다.
다음은 콜백 함수를 사용하여 옵저버 패턴을 구현한 예이다:
// 주제 객체 정의
const subject = {
state: 'initial state',
observers: [],
// 옵저버를 추가하는 메서드
addObserver: function(observer) {
this.observers.push(observer);
},
// 옵저버를 제거하는 메서드
removeObserver: function(observer) {
const index = this.observers.indexOf(observer);
if (index !== -1) {
this.observers.splice(index, 1);
}
},
// 옵저버에게 알림을 보내는 메서드
notifyObservers: function() {
this.observers.forEach(observer => observer(this.state));
},
// 상태를 업데이트하는 메서드
setState: function(newState) {
this.state = newState;
this.notifyObservers();
}
};
// 옵저버 함수 정의
const observer1 = state => console.log(`Observer 1: ${state}`);
const observer2 = state => console.log(`Observer 2: ${state}`);
// 주체에 옵저버 추가
subject.addObserver(observer1);
subject.addObserver(observer2);
// 주체의 상태 업데이트
subject.setState('new state');
// Output:
// Observer 1: new state
// Observer 2: new state
// 주체로부터 observer2 제거
subject.removeObserver(observer2);
// 주체의 상태 업데이트
subject.setState('another new state');
// Output:
// Observer 1: another new state
이 예제에서 주체 객체는 옵저버 배열에 옵저버 함수 목록을 유지한다.
setState() 메서드가 호출되면 주체 객체의 상태 속성을 업데이트하고 notifyObserver() 메서드를 호출하여 옵저버 배열을 반복하고 새 상태를 인수로 사용하여 각 옵저버 함수를 호출한다.
observer1 및 observer2 함수는 주체 객체에 옵저버로 추가되며, setState() 메서드가 호출될 때 상태 변경에 대한 알림을 받는다.
observer2 함수는 나중에 removeObserver() 메서드를 사용하여 주체 객체에서 제거되므로 더 이상 상태 변경에 대한 알림을 받지 않는다.
옵저버 패턴의 한 가지 장점은 개체 간의 느슨한 결합을 촉진한다는 점이다.
옵저버는 등록 및 알림을 위해 노출되는 인터페이스 외에는 주체에 대해 아무것도 알 필요가 없다. 따라서 주체나 다른 옵저버에게 영향을 주지 않고 옵저버를 쉽게 추가하거나 제거할 수 있다.
전반적으로 옵저버 패턴은 변화하는 요구 사항과 조건에 쉽게 적응할 수 있는 분리된 이벤트 중심 시스템을 구축하기 위한 강력한 기술이다.
2. Observer Pattern 연습 코드
ChatGPT에게 "Give me a challenge to practice the Observer Pattern in JavaScript."라고 질문한 뒤 나온 문제와 그에 대한 답이다.

스켈레톤 코드는 다음과 같다.
class Observer {
// TODO: Implement the Observer class with a subscribe() method and a notify() method
}
class Subject {
constructor() {
this.observers = [];
}
registerObserver(observer) {
// TODO: Implement the registerObserver() method
}
unregisterObserver(observer) {
// TODO: Implement the unregisterObserver() method
}
notifyObservers() {
// TODO: Implement the notifyObservers() method
}
}
// Usage
const subject = new Subject();
// Create two observers
const observer1 = new Observer();
const observer2 = new Observer();
// Register the observers with the subject
subject.registerObserver(observer1);
subject.registerObserver(observer2);
// Notify the observers
subject.notifyObservers();
// Unregister one observer
subject.unregisterObserver(observer1);
// Notify the remaining observer
subject.notifyObservers();
이를 구현한 코드는 다음과 같다.
class Observer {
constructor() {
this.subscribers = [];
}
subscribe(callback) {
this.subscribers.push(callback);
}
notify() {
this.subscribers.forEach(callback => callback());
}
}
class Subject {
constructor() {
this.observers = [];
}
registerObserver(observer) {
this.observers.push(observer);
}
unregisterObserver(observer) {
this.observers = this.observers.filter(ob => ob !== observer);
}
notifyObservers() {
this.observers.forEach(observer => observer.notify());
}
}
// Usage
const subject = new Subject();
// Create two observers
const observer1 = new Observer();
const observer2 = new Observer();
observer1.subscribe(data => console.log('observer1 received notify.'));
observer2.subscribe(data => console.log('observer2 received notify.'));
// Register the observers with the subject
subject.registerObserver(observer1);
subject.registerObserver(observer2);
// Notify the observers
subject.notifyObservers();
// output
// observer1 received notify.
// observer2 received notify.
// Unregister one observer
subject.unregisterObserver(observer1);
// Notify the remaining observer
subject.notifyObservers();
// output
// observer2 received notify.
'Web > JS' 카테고리의 다른 글
[JS] 디자인 패턴(Design Pattern)_어댑터 패턴(Adapter Pattern) (0) | 2023.02.27 |
---|---|
[JS] 디자인 패턴(Design Pattern)_데코레이터 패턴(Decorator Pattern) (0) | 2023.02.26 |
[JS] 디자인 패턴(Design Pattern)_팩토리 패턴(Factory Pattern) (0) | 2023.02.23 |
[JS] 디자인 패턴(Design Pattern)_싱글톤 패턴(Singleton Pattern) (0) | 2023.02.20 |
[JS] 디자인 패턴(Design Pattern)_공개 모듈 패턴(Revealing Module Pattern) (0) | 2023.02.18 |