C++의 template을 이용해서 Observer를 구현하는 것에 대한 단계적 설명입니다. 원본은 데브피아에서 김태현(tipani)님이 올려 놓으신 글을 기반으로 작성했으며 한단계 더 업그레이드 했습니다. 제가 늘 느껴오는 것이지만 C++의 template은 기존의 클래스간 관계도에 한정해 볼적에 그 디자인을 획기적으로 개선한다는 점에서 그 판도를 확 바꿀 수 있는 강력한 개념이라고 생각합니다. 아무쪼록 제가 김태현님의 글을 보고 매우 재미있게 template에 한발짝 다가섯듯이 여러분도 제 글을 통해 template에 한발짝 다가 설수있다면 정말 기쁘겠습니다. 참고로 이 글을 읽기 전에 Observer 패턴이 무엇인지 패턴입문서를 살펴보시길 바랍니다. 또한 이 글의 진행은 단계 단계 개선해 나가는 흐름으로 진행된다는 점에 유의하시길 바랍니다.
먼저 1단계입니다. 아래의 코드는 Observer들의 관리에 대한 책임을 맡고 있는 Observed 클래스입니다.
templateclass Observed { public: Observed() {} typedef std::list typeObservers; virtual ~Observed() {} void RegisterObserver(T *pOb) { m_listObserver.push_back( pOb ); } void UnRegisterObserver(T *pOb) { m_listObserver.remove(pOb); } protected: typeObservers m_listObserver; };
Observed가 관리하는 Observer 클래스인 Observabe 입니다. 단순히 Observed가 호출할 Observer의 OnEvent 함수가 순수가상함수로 선언되어 있습니다.
class Observable { virtual void OnEvent(int a) = 0; };
그리고 아래는 Obserable를 상속받아 구현한 클래스들입니다.
class Observable_A : public Observable { virtual void OnEvent(int a) { std::cout << "Fire_A -> " << a << std::endl; } }; class Observable_B : public Observable { virtual void OnEvent(int a) { std::cout << "Fire_B -> " << a << std::endl; } };
이제 마지막으로 Observed가 자신이 관리하고 있는 Observable의 OnEvent를 호출해 줘야 하는데, Observed 클래스는 자신이 관리하고 있는 Observable의 타입을 모르기 때문에 Observed와 Observable의 관계를 연결해 주기 위한, Observed로부터 상속받은 EventSrc 클래스가 필요합니다.
class EventSrc : public Observed{ void Fire(int a) { typeObservers::itrator it; for(it=m_listObserver.begint(); it!=m_listObserver.end; ++it) { (*it)->OnEvent(a); } } };
드디어 1단계의 Observer 패턴의 구현이 완성되었습니다. 실제 사용하는 예는 다음과 같습니다.
int main() { EventSrc *pES = new EventSrc(); Observable *pO_A = new Observale_A(); Observable *pO_B = new Observale_B(); pES->RegisterObserver(pOA); pES->RegisterObserver(pOB); pES->Fire(99); delete pO_B; delete pO_A; delete pES; return 0; }
1단계에서 산출된 소스만으로도 충분할 수도 있겠지만, 큰 문제점이 하나 있습니다. 그것은 바로 SRP(Single Responsiblity Principle)를 위반한다는 사실입니다. 즉, Obserable를 관리하는 책임을 Observed와 EventSrc라는 두개의 클래스가 책임을 나눠서 지고 있다는 점입니다. 그럴수밖에 없는 이유는 본문에 언급을 했구요.
이제 다음 2단계 이후부터는 이러한 SRP의 원칙을 지켜나가는 것을 해결문제로 다뤄나가면서 점차적으로 개선된 Observer 패턴을 구현해보겠습니다.
좋은글 잘 보고 갑니다..제 블로그에 링크겁니다.^^
네, 관리하고 계시는 블로그 주소가 어떻게 되시나요? 종종 놀러가고 싶습니다. ^^
thank you for good post.
but, OnEvent() function should be public!! as you know, ^^
Fire() also.
thanks 🙂 you are right! my mistyping of public!!