觀察者的實現和填坑

2021-07-11 05:51:26 字數 2057 閱讀 4490

觀察者模式在工程專案裡具有非常廣泛的應用,本文聊一聊自己對觀察者模式的一些理解和實現。

按照我自己的風格,我非常不贊同講各種原理看起來深入淺出頭頭是道最後就貼幾句偽**甚至偽**都沒有就完事的部落格方式。既然寫在部落格上了,就是為了供他人討論和借鑑。簡而言之,上**,講道理。

#include 

#include

using

namespace

std;

#include

#include

class subject;

class iobserver

;class subject

void detach(iobserver *obs)

}void trigger()

}private:

boost::mutex m_mutex;

list

m_ptrobservers;

};class observer : public iobserver

};int main()

subject.trigger();

return

0;}

當然這其中的問題是多方面的,顯然,在trigger裡面,(*it)->ontrigger(this),如果觀察者在自己的實現中做了detach或者atach其他指標的操作,那麼死鎖是不可避免的了。因此最好使用遞迴鎖:

boost::recursive_mutex m_mutex;

上鎖時:

boost::recursive_mutex::scoped_lock lock(m_mutex);

這樣是不是問題就解決了呢?顯然問題仍然非常嚴重:由於detach或者atach操作修改了容器內的結構,因此在

for (listiter it = m_ptrobservers.begin(); it != m_ptrobservers.end(); ++it)

這段**時,迭代器失效會直接導致程式的崩潰。

如何解決這樣的問題,這裡就需要一些技巧了。

#include 

#include

using

namespace

std;

#include

#include

class subject;

class iobserver

;class subject

void atatch(iobserver *obs)

else

--m_nusecount;

}void detach(iobserver *obs)

--m_nusecount;

}void trigger()

m_ptrtoadd.clear();

}for (listiter it = m_ptrobservers.begin(); it != m_ptrobservers.end(); )

else}}

--m_nusecount;

}private:

boost::recursive_mutex m_mutex;

list

m_ptrobservers;

list

m_ptrtoadd;

int m_nusecount;

};class observer : public iobserver

};int main()

subject.trigger();

return

0;}

這一次,我們使用了乙個usercount作標記,用來標誌當前有幾處正在訪問觀察者列表,如果發現其他處在訪問,那麼盡量避免直接add或者erase一類會使迭代器失效的操作,等到有機會以遍歷觀察者列表並且只有當前處在訪問該列表時,再做真正的增加或刪除操作。

另外,還有更加精妙的方案來可以解決我們繁瑣的使用usercount自己進行++,–操作,那就是通過智慧型指標的機制實現copy_on_write-ref_on_read,打算再開一篇博文貼**講原理。

觀察者模式實現

公升級觀察者 var observer function 定義介面 return else trigger方法用於觸發觀察者物件中的事件 type 要觸發的事件名稱 trigger用於觸發觀察者物件中的事件 trigger function type,val off方法用於移除某個事件 off fu...

PHP實現觀察者模式

特點 觀察者模式定義物件的一對多依賴,這樣一來,當乙個物件改變狀態時,它的所有依賴者都會收到通知並自動更新 觀察者模式利用 組合 將許多觀察者組合進主題中。物件 觀察者 主題 之間的這種關係不是通過繼承產生的,而是在執行時利用組合的方式產生的。多用組合,少用繼承!觀察者模式的優點和缺點 觀察者模式的...

C 實現觀察者模式

定義物件間的一種一對多的依賴關係,當乙個物件的狀態發生改變時,所有依賴於它的物件都得到通知並被自動更新。完美的將觀察者和被觀察的物件分離開。有時又被稱為 模型 檢視 view 模式 源 收聽者 listener 模式 或為發布 訂閱模式 目標就是通知的發布者,觀察者是通知的訂閱者 接受通知 obse...