etc.
[Design Pattern] 옵저버 패턴(Observer Pattern)
mooni_
2025. 4. 6. 20:22
옵저버 패턴(Observer Pattern) : 주체가 객체의 상태 변화가 있을 때마다 메서드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 패턴
> 주체 : 객체의 상태 변화를 보고 있는 관찰자
> 옵저버 : 객체의 상태 변화에 따라 전달되는 메서드 등을 기반으로 '추가 변화 사항'이 생기는 객체들을 의미
- MVC(Model-View-Controller) 패턴에 사용됨
- model(주체)에서 변경사항이 생겨 update() 메서드를 view(옵저버)에 알려주고 이를 기반으로 controller 작동
EX) Java에서의 Observer
1. Subject interface
interface Subject {
void register(Observer obj);
void unregister(Observer obj);
void notifyObservers();
Object getUpdate(Observer obj);
}
=> 옵저버 등록/제거 및 전체에게 알림을 보내는 등의 규칙 정의
2. Observer interface
interface Observer {
void update();
}
=> Subject가 메세지를 보낼 때 호출하는 메서드
3. Topic class
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();
}
}
=> 실제 Subject 구현
=> postMessage()로 새로운 메세지를 게시하면 내부 message를 업데이트하고 등록된 옵저버에게 notifyObservers()를 통해 알림
4. TopicSubscriber class
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);
}
}
=> 실제 Observer 구현
=> update()가 호출되면 topic.getUpdate()를 통해 메세지를 가져옴
5. main()
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!!");
}
}
=> Observer 3개 등록 -> 메세지 게시 후 등록된 옵저버에게 알림 -> 각 옵저버가 메세지 출력
EX) JavaScript에서의 Observer : 프록시 객체를 통해 구현 가능
const handler = {
get: function(target, name) {
return name === 'name' ? `${target.a} ${target.b}` : target[name];
}
};
const p = new Proxy({ a: 'MOONI', b: 'KIM' }, handler);
console.log(p.name); // MOONI KIM
> 프록시 객체 : 어떠한 대상의 기본적인 동작의 작업을 가로챌 수 있는 객체
> JS에서 프록시 객체의 매개변수 : target(프록시할 대상), handler(target 동작을 가로채고 동작의 내용을 담은 함수)
- get() 트랩을 정의함으로써, 속성 접근 시 커스텀 로직을 실행할 수 있습니다.
- p.name을 호출하면 handler.get()이 실행되어, a와 b 속성 값을 조합해서 반환하게 됩니다.