티스토리 뷰
언론사나 매거진 등은 구독 서비스를 제공한다. 해당 매체에 구독을 신청하게 되면 구독자가 직접 매체에 방문하지 않더라도 매체에 새로운 글이 발행되는 등의 이벤트에 따라 구독자에게 메일을 전송해 알려준다. 그럼 구독자는 메일을 보고 글을 읽는 등의 이벤트를 처리하게 된다.
옵저버 패턴은 이와 동일하다. 옵저버 패턴은 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들한테 연락이 가고 자동으로 내용이 갱신되는 방식으로 일대다(one-to-many) 의존성을 정의한다. 옵저버 패턴의 참여자는 둘로 나뉜다.
- 주제 객체(subject) : 언론사나 매거진 같이 데이터를 제공하는 객체
- 옵저버(observer) : 주제 객체를 구독하고 있는 객체
옵저버 객체들은 주제 객체를 구독한다.
주제 객체의 상태가 업데이트되면 주제 객체는 각 옵저버 객체에 업데이트된 상태를 알려준다.
이를통해 옵저버 패턴은 subject와 observer 사이의 느슨한 결합을 제공하고 observer의 자동화된 업데이트를 가능하게 한다.
구현
주제 객체와 옵저버 객체는 각각 해야할 행동들을 일반화할 수 있기 때문에 추상화하여 인터페이스로 만들 수 있다.
Observer Interface
Observer 인터페이스에는 Subject가 notify 했을 때 행동할 메서드인 1가지 메서드만 포함되면 된다.
public interface Observer {
void update();
}
Subject Interface
Subject 인터페이스에는 3가지의 메서드가 필요하다.
- registerObserver(Observer o) : 옵저버를 등록 (구독신청)
- removeObserver(Observer o) : 옵저버를 해제 (구독해제)
- notifyObservers() : 옵저버들에게 상태가 업데이트 됐음을 알림
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
이 두 인터페이스를 활용해서 매거진에 새로운 글이 등록되었을 때 구독자들에게 알림을 제공하는 경우를 구현해보자.
Subscriber
구독자는 Observer가 되므로 Observer 인터페이스를 구현한다.
public class Subscriber implements Observer {
private String id;
public Subscriber(String id) {
this.id = id;
}
@Override
public void update() {
System.out.println(id + ": 칼럼 읽기");
}
}
Magazine
매거진은 Subject이므로 Subject 인터페이스를 구현한다.
public class Magazine implements Subject {
private List<Observer> subscribers = new ArrayList<>();
public void newColumn() {
System.out.println("<새로운 칼럼 등록>");
notifyObservers(); // 구독자들에게 새로운 갈럼이 등록되었음을 알림
}
@Override
public void registerObserver(Observer observer) {
subscribers.add(observer); // 구독자 등록
}
@Override
public void removeObserver(Observer observer) {
subscribers.remove(observer); // 구독자 해제
}
@Override
public void notifyObservers() {
for (Observer subscriber : subscribers) {
subscriber.update(); // 구독자가 정의한 행동 실행
}
}
}
`newColumn()` 메서드로 매거진에 새로운 칼럼이 등록되었을 때 메서드 내부의 `notifyObservers()` 메서드로 구독자들에게 새로운 칼럼이 등록되었음을 알린다. 구독자는 자신이 정의한 `update()` 함수로 칼럼을 읽게 된다.
간단한 테스트
매거진에 3명의 구독자가 구독을 신청하고 매거진에서 새로운 칼럼이 등록되었을 경우와 이후에 구독자3이 구독 해제를 한 후 새로운 칼럼이 등록되었을 경우를 테스트하는 `main()` 이다.
public class Main {
public static void main(String[] args) {
Magazine magazine = new Magazine();
Subscriber subscriber1 = new Subscriber("subscriber1");
Subscriber subscriber2 = new Subscriber("subscriber2");
Subscriber subscriber3 = new Subscriber("subscriber3");
// 구독 신청
magazine.registerObserver(subscriber1);
magazine.registerObserver(subscriber2);
magazine.registerObserver(subscriber3);
// 새로운 칼럼 등록
magazine.newColumn();
System.out.println("--------------------");
// 구독자3의 구독 해제
magazine.removeObserver(subscriber3);
// 새로운 칼럼 등록
magazine.newColumn();
}
}
최초에 3명의 구독자가 매거진을 구독하며 매거진에서 새로운 칼럼이 발행된다. 새로운 칼럼이 발행되었을 때 3명의 구독자는 모두 칼럼을 읽을 것이다. 이후 구독자3이 구독을 취소한 후 매거진에 새로운 칼럼이 발행된다면 2명의 구독자는 새로운 칼럼을 읽게 될 것이다.
'CS > Design Pattern' 카테고리의 다른 글
Strategy Pattern (1) | 2024.12.17 |
---|---|
Singleton Pattern (0) | 2024.12.10 |