Observer观察者模式
作用:观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己
UML图:
Subject类,可翻译为主题或抽象通知者,一般用一个抽象类或者一个借口实现。它把所有对观察者对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个借口,可以增加和删除观察者对象。
Observer类,抽象观察者,为所有的具体观察者定义一个借口,在得到主题的通知时更新自己。这个借口叫做更新接口。抽象观察者一般用一个抽象类或者一个接口实现。更新接口通常包含一个Update()方法。
ConcreteSubject类,叫做具体主题或具体通知者,将有关状态存入具体通知者对象;在具体主题的内部状态改变时,给所有等级过的观察者发出通知。通常用一个具体子类实现。
ConcreteObserver类,具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。具体观察者角色可以保存一个指向一个具体主题对象的引用。
特点:将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。
何时使用:
当一个对象的改变需要同时改变其他对象的时候,而且它不知道具体有多少对象有待改变时,应该考虑使用观察者模式。
观察者模式所做的工作其实就是在解除耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。
代码如下:
Observer.h
1 #ifndef _OBSERVER_H_ 2 #define _OBSERVER_H_ 3 4 #include <string> 5 #include <list> 6 using namespace std; 7 8 class Subject; 9 10 class Observer 11 { 12 public: 13 ~Observer(); 14 virtual void Update(Subject*)=0; 15 protected: 16 Observer(); 17 private: 18 }; 19 20 class ConcreteObserverA : public Observer 21 { 22 public: 23 ConcreteObserverA(); 24 ~ConcreteObserverA(); 25 virtual void Update(Subject*); 26 protected: 27 private: 28 string m_state; 29 }; 30 31 class ConcreteObserverB : public Observer 32 { 33 public: 34 ConcreteObserverB(); 35 ~ConcreteObserverB(); 36 virtual void Update(Subject*); 37 protected: 38 private: 39 string m_state; 40 }; 41 42 class Subject 43 { 44 public: 45 ~Subject(); 46 virtual void Notify(); 47 virtual void Attach(Observer*); 48 virtual void Detach(Observer*); 49 virtual string GetState(); 50 virtual void SetState(string state); 51 protected: 52 Subject(); 53 private: 54 string m_state; 55 list<Observer*> m_lst; 56 }; 57 58 class ConcreteSubjectA : public Subject 59 { 60 public: 61 ConcreteSubjectA(); 62 ~ConcreteSubjectA(); 63 protected: 64 private: 65 }; 66 67 class ConcreteSubjectB : public Subject 68 { 69 public: 70 ConcreteSubjectB(); 71 ~ConcreteSubjectB(); 72 protected: 73 private: 74 }; 75 76 #endif
Observer.cpp
1 #include "Observer.h" 2 #include <iostream> 3 #include <algorithm> 4 5 using namespace std; 6 7 Observer::Observer() 8 {} 9 10 Observer::~Observer() 11 {} 12 13 ConcreteObserverA::ConcreteObserverA() 14 {} 15 16 ConcreteObserverA::~ConcreteObserverA() 17 {} 18 19 void ConcreteObserverA::Update(Subject* pSubject) 20 { 21 this->m_state = pSubject->GetState(); 22 cout << "The ConcreteObserverA is " << m_state << std::endl; 23 } 24 25 ConcreteObserverB::ConcreteObserverB() 26 {} 27 28 ConcreteObserverB::~ConcreteObserverB() 29 {} 30 31 void ConcreteObserverB::Update(Subject* pSubject) 32 { 33 this->m_state = pSubject->GetState(); 34 cout << "The ConcreteObserverB is " << m_state << std::endl; 35 } 36 37 Subject::Subject() 38 {} 39 40 Subject::~Subject() 41 {} 42 43 void Subject::Attach(Observer* pObserver) 44 { 45 this->m_lst.push_back(pObserver); 46 cout << "Attach an Observer\n"; 47 } 48 49 void Subject::Detach(Observer* pObserver) 50 { 51 list<Observer*>::iterator iter; 52 iter = find(m_lst.begin(),m_lst.end(),pObserver); 53 if(iter != m_lst.end()) 54 { 55 m_lst.erase(iter); 56 } 57 cout << "Detach an Observer\n"; 58 } 59 60 void Subject::Notify() 61 { 62 list<Observer*>::iterator iter = this->m_lst.begin(); 63 for(;iter != m_lst.end();iter++) 64 { 65 (*iter)->Update(this); 66 } 67 } 68 69 string Subject::GetState() 70 { 71 return this->m_state; 72 } 73 74 void Subject::SetState(string state) 75 { 76 this->m_state = state; 77 } 78 79 ConcreteSubjectA::ConcreteSubjectA() 80 {} 81 82 ConcreteSubjectA::~ConcreteSubjectA() 83 {} 84 85 ConcreteSubjectB::ConcreteSubjectB() 86 {} 87 88 ConcreteSubjectB::~ConcreteSubjectB() 89 {}
main.cpp
#include "Observer.h" #include <iostream> using namespace std; int main() { Observer* p1 = new ConcreteObserverA(); Observer* p2 = new ConcreteObserverB(); Observer* p3 = new ConcreteObserverA(); Subject* pSubject = new ConcreteSubjectA(); pSubject->Attach(p1); pSubject->Attach(p2); pSubject->Attach(p3); pSubject->SetState("old"); pSubject->Notify(); cout << "-------------------------------------" << endl; pSubject->SetState("new"); pSubject->Detach(p3); pSubject->Notify(); return 0; }
结果如下: