옵저버 패턴 (Observer Pattern)
Gof Design Pattern2014. 2. 1. 06:48
Observer Pattern - 옵저버 패턴
- 한 객체의 상태가 바뀌면 그 객체에 이존하는 다른 객체들 모두에게 연락이 가고 자동으로 내용이 갱신되는 패턴
- 1 : N(다) 의 의존성으로 정의한다
- 일방적 통지 (Broadcast) 방식의 패턴
샘플 코드)
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | //------------------------------------------------------------------ // Observer 인터페이스 class Observer { public: virtual void update() = 0; }; //------------------------------------------------------------------ // ConcreteObserver 상속 클래스 class ConcreteObserver : public Observer { public: void update() override { cout << this << " : update" << endl; } }; //------------------------------------------------------------------ // Subject 인터페이스 (옵저버들 관리 및 통지) class Subject { public: void attach(Observer* o) { mList.AddTail(o); } void detach(Observer* o) { mList.RemoveAt(mList.Find(o)); } protected: void notify() { POSITION pos = mList.GetHeadPosition(); while (pos != NULL) mList.GetNext(pos)->update(); } public: virtual void change() = 0; private: CAtlList<Observer*> mList; }; //------------------------------------------------------------------ // ConcreteSubject 상속 클래스 class ConcreteSubject : public Subject { public: void change() override { notify(); } }; //------------------------------------------------------------------ // Main int _tmain(int argc, _TCHAR* argv[]) { Subject* pSubject = new ConcreteSubject; Observer* pObserver1 = new ConcreteObserver; Observer* pObserver2 = new ConcreteObserver; Observer* pObserver3 = new ConcreteObserver; pSubject->attach(pObserver1); pSubject->attach(pObserver2); pSubject->attach(pObserver3); pSubject->change(); pSubject->detach(pObserver1); pSubject->detach(pObserver2); pSubject->detach(pObserver3); pSubject->change(); delete pSubject; delete pObserver1; delete pObserver2; delete pObserver3; return 0; } |
예제를 통한 옵저버 패턴(Observer Pattern) 알아보기
예제) 방송사 -> 시청자 관계를 통한 예제
방송사와 옵저버(시청자)와의 관계를 예를 들었습니다. 방송사는 시청자들을 하나의 컨테이너(리스트)에서 관리하고 시청등록자들에게 방송을 송출하는 부분을 맡고 있고, 옵저버 - 시청자쪽에서는 방송사에서 오는 방송을 그대로 방송시청하도록 1 : N 의 관계로 옵저버 패턴을 설계하였습니다.
예제 코드)
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | #include <atlcoll.h> #if _UNICODE typedef wstring tstring; #else typedef string tstring; #endif //------------------------------------------------------------------ // Observer 인터페이스 class 옵저버_인터페이스 { public: virtual void 방송시청(const TCHAR* news) = 0; virtual const TCHAR* 이름() const = 0; }; //------------------------------------------------------------------ // ConcreteObserver 상속 클래스 class 시청자 : public 옵저버_인터페이스 { public: 시청자(const TCHAR* name) : mName(name) {} public: void 방송시청(const TCHAR* news) override { cout << mName << " : " << news << endl; } const TCHAR* 이름() const { return mName.c_str(); } private: tstring mName; }; //------------------------------------------------------------------ // Subject 인터페이스 (옵저버들 관리 및 통지) class 방송사_인터페이스 { public: void 방송시청등록(옵저버_인터페이스* o) { mList.AddTail(o); cout << "방송 신청 : " << o->이름() << endl; } void 방송시청해제(옵저버_인터페이스* o) { mList.RemoveAt(mList.Find(o)); cout << "방송 해지 : " << o->이름() << endl; } protected: void 송출(const TCHAR* news) { POSITION pos = mList.GetHeadPosition(); while (pos != NULL) mList.GetNext(pos)->방송시청(news); } public: virtual void 뉴스(const TCHAR* news) = 0; private: CAtlList<옵저버_인터페이스*> mList; }; //------------------------------------------------------------------ // ConcreteSubject 상속 클래스 class 코리아방송 : public 방송사_인터페이스 { public: void 뉴스(const TCHAR* news) override { 송출(news); } }; //------------------------------------------------------------------ // Main int _tmain(int argc, _TCHAR* argv[]) { 방송사_인터페이스* pSubject = new 코리아방송; 옵저버_인터페이스* pObserver1 = new 시청자("홍길동"); 옵저버_인터페이스* pObserver2 = new 시청자("태평양"); 옵저버_인터페이스* pObserver3 = new 시청자("비둘기"); pSubject->방송시청등록(pObserver1); pSubject->방송시청등록(pObserver2); pSubject->방송시청등록(pObserver3); pSubject->뉴스("날씨를 말씀드리겠습니다."); pSubject->방송시청해제(pObserver1); pSubject->방송시청해제(pObserver2); pSubject->뉴스("뉴스 속보입니다."); delete pSubject; delete pObserver1; delete pObserver2; delete pObserver3; return 0; } |
예제 결과)
'Gof Design Pattern' 카테고리의 다른 글
커멘트 패턴 (Command Pattern) (2) | 2014.02.03 |
---|---|
디자인 패턴 관계도 (Design Pattern Relationships) (0) | 2014.02.01 |
메멘토 패턴 (Memento Pattern) (0) | 2014.01.30 |
파사드 패턴 (Facade Pattern) (0) | 2014.01.30 |
플라이웨이트 패턴 (Flyweight Pattern) (1) | 2014.01.30 |