軟件領域中的設計模式為開發人員提供了一種使用專家設計經驗的有效途徑。設計模式中運用了面向對象編程語言的重要特性:封裝、繼承、多態,真正領悟設計模式的精髓是可能一個漫長的過程,需要大量實踐經驗的積累。最近看設計模式的書,對于每個模式,用C++寫了個小例子,加深一下理解。主要參考《大話設計模式》和《設計模式:可復用面向對象軟件的基礎》兩本書。本文介紹觀察者模式的實現。
觀察者模式:定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴于它的對象都得到通知并被自動更新。它還有兩個別名,依賴(Dependents),發布-訂閱(Publish-Subsrcibe)。可以舉個博客訂閱的例子,當博主發表新文章的時候,即博主狀態發生了改變,那些訂閱的讀者就會收到通知,然后進行相應的動作,比如去看文章,或者收藏起來。博主與讀者之間存在種一對多的依賴關系。下面給出相應的UML圖設計。

可以看到博客類中有一個觀察者鏈表(即訂閱者),當博客的狀態發生變化時,通過Notify成員函數通知所有的觀察者,告訴他們博客的狀態更新了。而觀察者通過Update成員函數獲取博客的狀態信息。代碼實現不難,下面給出C++的一種實現。
~~~
//觀察者
class Observer
{
public:
Observer() {}
virtual ~Observer() {}
virtual void Update() {}
};
//博客
class Blog
{
public:
Blog() {}
virtual ~Blog() {}
void Attach(Observer *observer) { m_observers.push_back(observer); } //添加觀察者
void Remove(Observer *observer) { m_observers.remove(observer); } //移除觀察者
void Notify() //通知觀察者
{
list<Observer*>::iterator iter = m_observers.begin();
for(; iter != m_observers.end(); iter++)
(*iter)->Update();
}
virtual void SetStatus(string s) { m_status = s; } //設置狀態
virtual string GetStatus() { return m_status; } //獲得狀態
private:
list<Observer* > m_observers; //觀察者鏈表
protected:
string m_status; //狀態
};
~~~
以上是觀察者和博客的基類,定義了通用接口。博客類主要完成觀察者的添加、移除、通知操作,設置和獲得狀態僅僅是一個默認實現。下面給出它們相應的子類實現。? ? ?
~~~
//具體博客類
class BlogCSDN : public Blog
{
private:
string m_name; //博主名稱
public:
BlogCSDN(string name): m_name(name) {}
~BlogCSDN() {}
void SetStatus(string s) { m_status = "CSDN通知 : " + m_name + s; } //具體設置狀態信息
string GetStatus() { return m_status; }
};
//具體觀察者
class ObserverBlog : public Observer
{
private:
string m_name; //觀察者名稱
Blog *m_blog; //觀察的博客,當然以鏈表形式更好,就可以觀察多個博客
public:
ObserverBlog(string name,Blog *blog): m_name(name), m_blog(blog) {}
~ObserverBlog() {}
void Update() //獲得更新狀態
{
string status = m_blog->GetStatus();
cout<<m_name<<"-------"<<status<<endl;
}
};
~~~
客戶的使用方式:
~~~
//測試案例
int main()
{
Blog *blog = new BlogCSDN("wuzhekai1985");
Observer *observer1 = new ObserverBlog("tutupig", blog);
blog->Attach(observer1);
blog->SetStatus("發表設計模式C++實現(15)——觀察者模式");
blog->Notify();
delete blog; delete observer1;
return 0;
}
~~~
本人享有博客文章的版權,轉載請標明出處?[http://blog.csdn.net/wuzhekai1985](http://blog.csdn.net/wuzhekai1985)