C++공부/GoF의 디자인 패턴
감시자(Observer)
아헿헿헿
2022. 6. 1. 16:45
1. 용도
객체 사이에 일 대 다의 의존 관계를 두어, 어떤 객체의 상태가 변할 떄 그 객체에 의존성을 가진 다른 객체들이 그 변화를 통지받고 자동으로 갱신될 수 있게 만듭니다.
2. 활용성
- 어떤 추상 개념이 두 가지 양상을 갖고 하나가 다른 하나에 종속적일 때, 각 양상을 별도의 객체로 캡슐화하여 이들 각각을 재사용할 수 있습니다.
- 한 객체에 가해진 변경으로 다른 객체를 변경해야 하고, 프로그래머들은 얼마나 많은 객체들이 변경되어야 하는지 몰라도 될 때
- 어떤 객체가 다른 객체에 자신의 변화를 통보할 수 있는데, 그 변화에 관심 있어 하는 객체들이 누구인지에 대한 가정 없이도 그러한 통보가 될 때
3. Class Diagram과 구조
[Subject] - 감시자들을 알고 있는 주체입니다. 감시자 객체를 붙이거나 떼는 데 필요한 인터페이스를 제공합니다.
[Observer] -subject에 생긴 변화에 관심 있는 객체를 갱신하는 데 필요한 인터페이스르 정의합니다.
[ConcreteSubject] - ConcreteObserver 객체에게 알려주어야 하는 상태를 저장하며 변경될 때 변경을 통보합니다.
[ConcreteObject] - ConcreteSubject 객체에 대한 참조자를 관리합니다. 주체의 상태와 일관성을 유지해야 하는 상태를 저장합니다.
ConcreteSubject는 Observer의 상태와 자신의 상태가 달라지는 변경이 발생할 때 마다 감시자에게 통보하며, 통보된 후, ConcreteObserver는 필요한 정보를 subject에 질의하여 subject의 상태와 자신의 상태를 일치시킵니다.
4. 장단점
subject와 observer 클래스 모두 독립적으로 변형하기 쉽고, 재사용하기도 좋습니다.
장점
- Subject와 Observer 클래스 간에는 추상적인 결합도만이 존재합니다 - Observer들은 클래스에 정의된 인터페이스만 따르기에, Subject들이 ConcreteObserver 클래스가 어떻게 동작하는 지에 대해 알지 않아도 됩니다. 따라서 서로 간의 결합은 추상적이며 최소화되어 있습니다.
- Boradcast 방식의 교류를 가능케 합니다. - subject 정보를 원하는 모든 객체에 자동적으로 전달되도록 하며, observer가 받은 통보를 어떻게 처리할지를 결정합니다.
단점
- 예측하지 못한 정보 갱신 - 감시자들은 다른 감시자들의 존재를 모르기에 subject 변경 비용을 알 수 없고, 잘 정의 및 유지된 경우에도 종속성 때문에 불필요한 갱신이 일어날 수 있으며 추적도 까다로울 수 있습니다. 별도의 프로토콜이 추가되지 않는 한 변경을 유추하는 작업이 어렵습니다.
5. 구현 방법
- subject와 observer의 대응 - 자신이 통보해 주어야 하는 observer들을 관리하기 위해 참조자를 저장합니다.
- 하나 이상의 주체 감시 - subject에서 자신을 매개변수화하여 observer가 어떤 주체를 확인하고 있는지 알 수 있도록 함.
- 갱신 시작 지점 지정 - Notify()에는 두가지 선택 사항이 존재하여, subject 클래스의 상태 변경 후 상태 지정 연산에서 호출하는 방법과, 사용자가 적시에 호출하도록 만드는 방법이 존재합니다.
- 삭제한 subject에 대한 dangling pointer 처리 - subject가 삭제된 경우 무효 참조자를 가지게 되는 것을 방지합시다
- 통보 전에 subject 상태 일관성 유지
- 감시자별 갱신 프로토콜 회피
- 자신이 관심 있는 변경 명확하게 지정 - subject 클래스에 자신이 관심 있는 이벤트에 대한 감시자를 등록하는 인터페이스를 정의하여 효율성을 높일 수 있습니다.
- 복잡한 갱신의 의미 구조 캡슐화- subject와 observer 간에 일어나는 관련성이 복잡하다면 이들 관련성을 관리하는 별도의 객체를 만들도록 합니다.