Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
Tags
- 안드로이드
- 최소힙
- 2941
- 백준
- 파이팅
- deque
- 1302
- Algorithm
- 1759
- 디자인패턴
- 백준 #알고리즘 # Algorithm #파이썬
- 1715
- 1697
- AOS
- Python
- BFS
- 파이썬
- 라이징프로그래머2 #Android #안드로이드 #Quitter #MakeUs
- 알고리즘
- 1766
- Heap
- 해커랭크
- 프로그래머스
- MVC
- 올바른 괄호
- level3
- python #7490 #백준 #알고리즘 #BFS
- CS
- REST API
- 12865
Archives
Liam 일지
옵저버 패턴 본문
728x90
옵저버 패턴이란
옵저버 패턴은 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴
- 한 객체의 상태 변화에 따라 다른 객체의 상태도 연동되도록 **일대다 객체 의존 관계를 구성**하는 패턴
- 데이터의 변경이 발생했을 경우 **상대 클래스나 객체에 의존하지 않으면서 데이터 변경을 통보하고자 할 때** 유용하다.
- ex) 새로운 파일이 추가되거나 기존 파일이 삭제되었을 때 탐색기는 다른 탐색기에게 즉시 변경을 통보해야한다.
- 옵저버 패턴은 통보 대상 객체의 관리를 Subject 클래스와 Observer 인터페이스로 일반화한다.
- 이를 통해 데이터 변경을 통보하는 클래스(ConcreteSubject)는 통보 대상 클래스나 객체에(ContcreteObserver)에 대한 의존성을 없앨 수 있다.
- 결과적으로 통보 대상 클래스나 대상 객체의 변경에도 통보하는 클래스(ConcreteSubject)를 수정 없이 그대로 사용할 수 있다.

역할이 수행하는 작업
- Observer
- 데이터의 변경을 통보 받는 인터페이스
- 즉, Subject에서는 Observer 인터페이스의 update메서드를 호출함으로써 ConcreteSubject의 데이터 변경을 ConcreteObserver에게 통보한다.
- Subject
- ConcreteObserver 객체를 관리하는 요소
- Observer 인터페이스를 참조해서 ConcreteObserver를 관리하므로 ConcreteObserver의 변화에 독립적일 수 있다.
- ConcreteSubject
- 변경 관리 대상이 되는 데이터가 있는 클래스(통보하는 클래스)
- 데이터의 변경을 위한 메서드인 setState가 있다.
- setState 메서드에서는 자신의 데이터인 subjectState를 변경하고 Subject의 notifyObservers 메서드를 호출해서 ConcreteObserver 객체에 변경을 통보한다.
- ConcreteObserver
- ConcreteSubject의 변경을 통보받는 클래스
- Observer인터페이스의 update 메서드를 구현함으로써 변경을 통보받는다.
- 변경된 데이터는 ConcreteSubject의 get State메서드를 호출함으로써 변경을 조회한다.
간단한 코드 예시
interface Subject{
public void attach(Observer o); // Subject에 Observer를 구독자로 등록한다.
public void detach(Observer o); // Subject에 등록한 Observer의 구독을 해지한다.
public void notify(); // Subject에서 모든 Observer에 정보를 전달한다.
}
class SubjectImpl implements Subject{
private List<Observer> observers= new ArrayList<>();
private Data data1;
private Data data2;
public void attach(Observer o){
observers.add(o);
}
public void detach(Observer o){
observers.remove(o);
}
public void notify(){
//모든 옵저버를 순회하며 업데이트 적용
for (Observer o: observers){
o.update(this);
}
}
public void setData1(Data d){
this.data1=d;
}
}
주의할점#
- 옵저버는 상태를 갖지 않아도 된다.
- 상태는 Subject의 담당이므로 Subject와 Observer의 일대다 관계가 성립한다.
- 예제에서는 Observer가 update를 통해 값을 전달받고 저장하지만, 상태를 굳이 저장할 필요가 없는 경우에는 상태를 저장하지 않아도 된다.
- Notify를 누가 호출해야할지
- GoF는 다음 두 가지 방법 중에서 선택하라고 권유한다.
- Subject에서 변경이 발생할 때, 변경을 저장하는 메소드가 Notify()를 호출하는 방법.
- 사용자(main 등)가 적절한 시기에 Notify()를 호출하는 방법.
- GoF는 다음 두 가지 방법 중에서 선택하라고 권유한다.
- Observer의 행위가 Subject에 영향을 주는 경우
- Subject가 notify를 호출한다.
- Observer의 update가 호출된다.
- Observer::update 실행도중 Subject에 영향을 준다.
- Goto 1
- 만약 Observer의 행위가 Subject에 영향을 주는 로직이 있다면, 무한 루프가 발생할 수 있으므로 주의할 필요가 있다.
관련 면접질문#
- 옵저버패턴을 사용하는 이유는 무엇인가요?
- -> Subject와 observer가 느슨하게 결합되어 있는 객체 디자인을 제공할 수 있다. 그로인해 옵저버의 추가, 제거가 자유로워 지고 새로운 형식의 옵저버를 추가하기도 쉬워진다. 예를 들면 Android의 EventListener처럼 대부분의 이벤트들이 옵저버 패턴 방식으로 사용되고 있다.
참고 자료:#
옵저버 패턴 :https://gmlwjd9405.github.io/2018/07/08/observer-pattern.html
'CS' 카테고리의 다른 글
| RESTful API란? (0) | 2021.05.10 |
|---|---|
| Tree (0) | 2021.05.01 |