窺探觀察者模式

  觀察者模式(obsever pattern)又名發行/訂閱模式(publish-subscribe pattern),是事件驅動模型的簡化版本,也是咱們熟知的MVC架構的核心部分。ios

 

下面以博客園訂閱博客爲例,窺探一下觀察者模式蘊含的奧祕:設計模式

  當博主發表新文章的時候,即博主狀態發生了改變,那些訂閱的讀者就會收到通知,而後進行相應的動做,好比去看文章,或者收藏起來。博主與讀者之間存在種一對多的依賴關係。架構

【對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴於它的對象都獲得通知並被自動更新】這就是觀察者模式,所謂的觀察者能夠理解爲關注博客的讀者被觀察的對象(Subject)即爲博主,博主自身狀態發生改變時會發出通知(Notify),讀者(Obsever)能夠經過更新操做(Update)得到博主的最新消息。測試

 

  觀察者模式的實現有如下4類角色:spa

  • 抽象主題(Subject:能夠用博客的抽象基類來理解,通常用一個抽象類或者一個接口實現。Subject提供依賴於它的觀察者 Observer 的註冊( Attach) 和註銷( Detach)操做,而且提供了使得依賴於它的全部觀察者同步的操做( Notify)。
  • 抽象觀察者(Observer:能夠用觀察者的抽象基類來理解,抽象觀察者通常用一個抽象類或者一個接口實現。在這個示意性的實現中,更新接口只包含一個方法(即Update()方法),這個方法叫作更新方法。
  • 具體主題(ConcreteSubject:就是你所關注的具體博主(若是你關注了我這個類就是acelit-cnblog),繼承自抽象博客,ConcreteSubject將有關狀態存入具體現察者對象;在具體主題的內部狀態改變時,給全部登記過的觀察者發出通知。
  • 具體觀察者(ConcreteObserver:也就是關注博客的讀者,繼承自抽象觀察者,ConcreteObserver存儲與主題的狀態自恰的狀態。具體觀察者實現抽象觀察者所要求的更新接口,以便使自己的狀態與主題的狀態相協調。    

 

  這麼說你們可能還不太理解,結合下面這張圖和實現代碼來分析:設計

  

觀察者模型所需4大類(obsever.h):code

 1 #include <iostream>
 2 #include <string>
 3 #include <list>
 4 #include <iterator>
 5 using namespace std;
 6 //觀察者  
 7 class Observer
 8 {
 9 public:
10     Observer() {}
11     virtual ~Observer() {}
12     virtual void Update() {}
13 };
14 //博客  
15 class Blog
16 {
17 public:
18     Blog() {}
19     virtual ~Blog() {}
20     void Attach(Observer *observer) { m_observers.push_back(observer); }     //添加觀察者  
21     void Remove(Observer *observer) { m_observers.remove(observer); }        //移除觀察者  
22     void Notify() //通知觀察者  
23     {
24         list<Observer*>::iterator iter = m_observers.begin();
25         for (; iter != m_observers.end(); iter++)
26             (*iter)->Update();
27     }
28     virtual void SetStatus(string s) { m_status = s; } //設置狀態  
29     virtual string GetStatus() { return m_status; }    //得到狀態  
30 private:
31     list<Observer* > m_observers; //觀察者鏈表  
32 protected:
33     string m_status; //狀態  
34 };
35 
36 //具體博客類  
37 class CNBlog : public Blog
38 {
39 private:
40     string m_name; //博主名稱  
41 public:
42     CNBlog(string name) : m_name(name) {}
43     ~CNBlog() {}
44     void SetStatus(string s) { m_status = "cnblog通知 : " + m_name + s; } //具體設置狀態信息  
45     string GetStatus() { return m_status; }
46 };
47 //具體觀察者  
48 class ObserverBlog : public Observer
49 {
50 private:
51     string m_name;  //觀察者名稱  
52     list<Blog* > m_blog;   //訂閱者鏈表
53 public:
54     ObserverBlog(string name) : m_name(name){}
55     ~ObserverBlog() {}
56     void Attach(Blog *blog) { m_blog.push_back(blog); }     //添加訂閱者  
57     void Remove(Blog *blog) { m_blog.remove(blog); }        //移除訂閱者    
58     void Update()  //得到更新狀態  
59     {
60 //爲了防止訂閱者重複輸出所觀察的博客,每次只輸出最後一個博主的更新消息
61         list<Blog*>::iterator iter = m_blog.end();
62         string status = (*(--iter))->GetStatus();
63         if (status != "")
64             cout << m_name << "-------" << status << endl;
65     }
66 };

測試代碼:server

 1 //測試代碼
 2 //3個觀察者,3個訂閱者,第1個觀測者訂閱了一、二、3號訂閱者,第1個訂閱者被一、二、3號觀察者關注。
 3 #include "obsever.h"
 4 
 5 int main()
 6 {
 7     Blog *blog1 = new CNBlog("acelit1");
 8     Blog *blog2 = new CNBlog("acelit2");
 9     Blog *blog3 = new CNBlog("acelit3");
10 
11     ObserverBlog *observer1 = new ObserverBlog("subscriber1");
12     ObserverBlog *observer2 = new ObserverBlog("subscriber2");
13     ObserverBlog *observer3 = new ObserverBlog("subscriber3");
14 
15     observer1->Attach(blog1);
16     observer2->Attach(blog1);
17     observer3->Attach(blog1);
18 
19     blog1->Attach(observer1);
20     blog1->Attach(observer2);
21     blog1->Attach(observer3);
22     blog1->SetStatus("發表設計模式C++實現——觀察者模式");
23     blog1->Notify();
24 
25     observer1->Attach(blog2);
26     blog2->Attach(observer1);
27     blog2->SetStatus(" published: observer pattern");
28     blog2->Notify();
29 
30     observer1->Attach(blog3);
31     blog3->Attach(observer1);
32     blog3->SetStatus(" published: 觀察者模式");
33     blog3->Notify();
34 
35     delete blog1; 
36     delete blog2;
37     delete blog3;
38     delete observer1;
39     delete observer2;
40     delete observer3;
41 
42     system("pause");
43     return 0;
44 }

測試結果:對象

博主acelit1狀態改變,observer1~3均更新狀態;博主acelit2和acelit3狀態改變,只有observer1更新狀態。blog

 

 

 全文完。歡迎各位老司機批評指正O(∩_∩)O

相關文章
相關標籤/搜索