❒ Description
Observer 패턴의 원리와 동작과정에 대해서 학습할 것이다.
또한 Observer 패턴의 예시를 들어 이해도를 높여보자.
❒ Observer 패턴이란?
주체가 어떤 객체(subject)의 상태 변화를 관찰하다가 상태 변화가 있을 때마다
메서드 등을 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 디자인 패턴.
상호작용하는 객체 사이에는 가능하면 느슨한 결합을 사용해야 하는데 Observer 패턴이 대표적이라고 할 수 있다.
또한 일대다(one-to-many) 의존성을 정의한다.
Observer 패턴은 여러 가지 방법으로 정의할 수 있지만, 보통은 주제 인터페이스와 Observer 인터페이스가 들어있는
클래스 디자인으로 구현하다.
Observer 패턴은 트위터, 인스타그램 등 SNS에서 주로 많이 사용한다고 한다.
새로운 트윗을 작성하면 나를 팔로우하고 있는 팔로워들에게 노티가 발송되는 것을 대표적으로 생각할 수 있다.
또한 신문사와 구독자들의 관계도 Observer 패턴으로 구현할 수 있다.
❒ Sudo Code
구독하고 있는 잡지의 구독료가 변경됐을 때 구독자들에세 노티를 발송하는 로직을
Observer 패턴을 적용하여 직접 예제를 만들면서 학습하자.
우선 두 개의 인터페이스와 각각 메소드들이 필요하다.
- Subject (구독자 추가 / 구독자 삭제 / 변경사항 알림)
- Observer (옵저버의 변경 정보 update)
그리고 위 인터페이스를 각각 구현한 구현체가 필요하다.
- MagazineCenter
- MagazineSubscriber
Subject & Observer
public interface Subject {
public void register(Observer obj);
public void unregister(Observer obj);
public void sendNotification();
}
public interface Observer {
public void update();
}
Magazine
public class Magazine implements Subject {
private List<Obserber> observers = new ArrayList<>();
private String title;
private String author;
private Money price;
//...
@Builder
public static Magazine newOne(Money price) {
return new Magazine(price);
}
public void updatePrice(Money price) {
this.price = price;
}
public void postMessage(String message, Money price) {
updatePrice(price);
sendNotifications();
}
@Override
public void register(Observer obj) {
this.observers.add(obj);
}
@Override
public void unregister(Observer obj) {
if (ObjetUtils.isEmpty(observers) {
thorw new NoObserverExistException();
}
this.observers.remove(obj);
}
@Override
public void sendNotifications() {
this.observers.forEach(Observer::update);
}
}
MagazineSubscriber
public class MagazineSubscriber implements Observer {
private String name;
private Subject magazine;
@Builder
public static MagazineSubscriber newOne(String name, Subject magazine) {
return new MagazineSubscriber(name, magazine);
}
@Override
public void update() {
String message = String.format("가격이 $d원으로 변경됐습니다.", magazine.getPrice())
System.out.println(message)
}
}
❒ Push or Pull
Observer 패턴을 구현할 때 2가지 데이터 보내는 방법을 생각할 수 있다.
- Push : Subject가 Observer로 데이터를 보내는 방식
- Pull : Observer가 Subject로 부터 데이터를 당겨오는 방식
위의 sudo code는 Pull 방식을 사용하여 작성한 코드이다. 이 방식을 사용하게 되면 Subject가 전송하는
데이터가 변경 될 때 Observer 쪽만 수정하면 되기 때문에 유지보수면에서 유리한 점이 있는 것 같다.
❒ Observer-Pattern in MVC
MVC를 패턴 관점에서 보면 여러 패턴들이 녹아있다. 그중 Observer 패턴 쪽만 들여다 보자.
하나의 Model에 대하여 다수의 View가 구독하는 형태를 가지고 있으며, 이 행위는 Controller에 의해 중재된다.
- Controller가 Model(Subject)에게 상태를 변경하라고 요청한다.
- 상태가 변경되면 Model(Subject)은 View(Observer)들에게 변경 사항을 통지(notifyAll)한다.
- View는 Model의 변경된 데이터를 반영하여 사용자에게 업데이트된 정보를 표시한다.
여기서 Model은 View나 Controller에게 전혀 의존하지 않는다.
그리고 Controller도 Observer가 될 수 있다. 예를 들면, Model에 있는 어떤 status에 따라서
view의 인터페이스 항목이 활성화 또는 비활성화되는 경우를 생각할 수 있다. 이런 경우에는
Controller가 View에게 상황에 맞게 화면을 갱신하라고 요청하게 된다.
❒ 핵심 정리
- 객체들 사이의 일대다(one-to-many)관계를 정의한다.
- Subject와 Observer는 느슨한 결합으로 연결되어 있기 때문에 서로 모른다.
- Subject가 데이터를 보내는 Push 방식과 Observer가 데이터를 당겨오는 Pull 방식이 있다.
- Pub-Sub 패턴과 유사하다 같다고 볼 순 없다.
- MVC에서 Observer 패턴이 자주 사용된다.
❒ 예상 면접 질문
1. Observer 패턴이란 무엇인가요?
주체의 상태 변화가 있을 때 이를 감지하고 자동으로 관련 객체들에게 통보하는 디자인 패턴입니다.
주로 Event 핸들링 시스템에서 사용되며, 주체(Subject)와 관찰자(Observer) 간의 일대다(one-to-many) 관계를 정의합니다.
2. Observer 패턴의 주요 구성 요소는 무엇인가요?
3. Observer 패턴의 장단점 및 사용시 주의 사항의 무엇인가요?
4. Observer 패턴과 Pub-Sub 패턴의 차이점은 무엇인가요?
'CS > Design Pattern' 카테고리의 다른 글
README.MD (0) | 2024.07.25 |
---|