我覺的很多文章都不保留版權的,我很多文章都被抄襲,卻沒有標明原作者和出處。
比如:
http://www.linuxidc.com/Linux/2013-04/82537p3.htm
http://www.07net01.com/linux/yizhiLINUXdewaiweishebeiqudongdaoQNXxitongzhong_162232_1365594620.html
http://www.cnblogs.com/xinyuyuanm/archive/2013/04/11/3014086.html
http://blog.chinaunix.net/uid-28305718-id-3577390.html
達內培訓:http://www.sctarena.com/Article/Article.asp?nid=4133
 
原封不動照抄我的,無一注明出處,有的還注明原創,我那個去也,這是我的文章(日期2013年4月9號),原文鏈接:
http://www.shnenglu.com/TianShiDeBaiGu/archive/2013/04/09/Driver__Linux_to_qnx.html
不止這一篇,希望以后有朋友轉走的留個出處,盜取別人的文章然后用自己的簽名是不道德的。


觀察者將自己注冊到被觀察者的容器中時,被觀察者不應該過問觀察者的具體類型,而是應該使用觀察者的接口。這樣的優點是:假定程序中還有別的觀察者,那么只要這個觀察者也是相同的接口實現即可。一個被觀察者可以對應多個觀察者,當被觀察者發生變化的時候,他可以將消息一一通知給所有的觀察者。基于接口,而不是具體的實現——這一點為程序提供了更大的靈活性。


觀察者 

(Observer)將自己注冊到被觀察對象(Subject)中,被觀察對象將觀察者存放在一個容器(Container)里。觀察者模式的作用是:當一個對象的狀態發生變化時,能夠自動通知其他關聯對象,自動刷新對象狀態。
觀察者模式有時又被稱為發布-訂閱Subscribe>模式、模型-視圖View>模式、源-收聽者Listener>模式或從屬者模式。

我在面試的時候被問道觀察者模式、MVC,結果沒反應過來。
在PPTV被問道點擊事件是怎么傳給圖形界面的,我也沒理解他在問這個問題,后來才恍然大悟,估計被鄙視了。
這片文章也算是順便證明一下我對設計模式的理解深度吧,我敢肯定的說,你們錯過了一個C++高手。

在C++的許多庫實現中、在MVC模型中、在博客訂閱系統中,都使用了觀察者模式。
對C++而言,這個模式最大的用處在于為C++添加事件概念(比如C#就直接在語法層面提供了事件的概念),像 object-c和JAVA提供委托,也是為了支持事件機制。

在《UNIX編程藝術》中提到軟件設計最重要的是正交,解耦。作為UNIX程序員我原本只知道這么告訴別人“數據與邏輯分離”、“將策略和機制分開”,后來應用程序界面設計者就是告訴我:這個東西是符合“Model-View-Control”的,然后我整理了一下才明白MVC也是觀察者模式的一種機制.

好了,我們省事一點,改百度百科的代碼吧。
原地址:
http://baike.baidu.com/view/1854779.htm

業務邏輯是:在MVC中,用戶界面可以作為一個觀察者,業務數據是被觀察者,用戶界面觀察業務數據的變化,發現數據變化后,就顯示在界面上。
UML圖如下:

觀察者

(Observer)將自己注冊到被觀察對象(Subject)中,被觀察對象將觀察者存放在一個容器(Container)里。

被觀察

被觀察對象發生了某種變化(如圖中的SomeChange),從容器中得到所有注冊過的觀察者,將變化通知觀察者。

撤銷觀察

觀察者告訴被觀察者要撤銷觀察,被觀察者從容器中將觀察者去除。
觀察者將自己注冊到被觀察者的容器中時,被觀察者不應該過問觀察者的具體類型,而是應該使用觀察者的接口。這樣的優點是:假定程序中還有別的觀察者,那么只要這個觀察者也是相同的接口實現即可。一個被觀察者可以對應多個觀察者,當被觀察者發生變化的時候,他可以將消息一一通知給所有的觀察者。基于接口,而不是具體的實現——這一點為程序提供了更大的靈活性。

C++代碼:
//filename observer.h
#include <iostream>
#include <set>
#include <string>
using namespace std;
/////////////////////抽象模式定義
class CObservable;
//觀察者,純虛基類
class CObserver
{
public:
    CObserver(){};
    virtual ~CObserver(){};
    //當被觀察的目標發生變化時,通知調用該方法
    
//來自被觀察者pObs, 擴展參數為pArg
    virtual void Update(CObservable* pObs, void* pArg = NULL) = 0;
};
//被觀察者,即Subject
class CObservable
{
public:
    CObservable() : m_bChanged(false) {};
    virtual ~CObservable() {};

    void Attach(CObserver* pObs);   //注冊觀察者
    void Detach(CObserver* pObs);   //注銷觀察者
    void DetachAll();               //注銷所有觀察者
    void Notify(void* pArg = NULL); //若狀態變化,則遍歷觀察者,逐個通知更新
    bool HasChanged();              //測試目標狀態是否變化
    int GetObserversCount();        //獲取觀察者數量
protected:
    void SetChanged();              //設置狀態變化!!!必須繼承CObservable才能設置目標狀態
    void ClearChanged();            //初始化目標為未變化狀態
private:
    bool m_bChanged;                //狀態
    set<CObserver*> m_setObs;       //set保證目標唯一性
};
/////////////////////抽象模式實現
void CObservable::Attach(CObserver* pObs){
    if (!pObs) return;
    m_setObs.insert(pObs);
}
void CObservable::Detach(CObserver* pObs){
    if (!pObs) return;
    m_setObs.erase(pObs);
}
void CObservable::DetachAll(){
    m_setObs.clear();
}
void CObservable::SetChanged(){
    m_bChanged = true;
}
void CObservable::ClearChanged(){
    m_bChanged = false;
}
bool CObservable::HasChanged(){
    return m_bChanged;
}
int CObservable::GetObserversCount(){
    return m_setObs.size();
}
void CObservable::Notify(void* pArg /* = NULL */){
    if (!HasChanged()) return;
    cout << "notify observers…" << endl;
    ClearChanged();
    set<CObserver*>::iterator itr = m_setObs.begin();
    for (; itr != m_setObs.end(); itr++){
        (*itr)->Update(this, pArg);
    }
}
/////////////////////具體應用類定義和實現
//bloger是發布者,即被觀察者(subject)
class CBloger : public CObservable
{
public:
    void Publish(const string &strContent){
        cout << "bloger publish, content: " << strContent << endl;
        SetChanged();
        Notify(const_cast<char*>(strContent.c_str()));
    }
};
//portal是發布者,即被觀察者(subject)
class CPortal : public CObservable
{
public:
    void Publish(const string &strContent){
        cout << "portal publish, content: " << strContent << endl;
        SetChanged();
        Notify(const_cast<char*>(strContent.c_str()));
    }
};
//RSS閱讀器,觀察者
class CRSSReader : public CObserver
{
public:
    CRSSReader(const string &strName) : m_strName(strName){}
    virtual void Update(CObservable* pObs, void* pArg = NULL){
        char* pContent = static_cast<char*>(pArg);
        //觀察多個目標
        if (dynamic_cast<CBloger*>(pObs)){
            cout << m_strName << " updated from bloger, content: " << pContent << endl;
        }else if (dynamic_cast<CPortal*>(pObs)){
            cout << m_strName << " updated from portal, content: " << pContent << endl;
        }
    }
private:
    string m_strName;
};
//Mail閱讀器,觀察者
class CMailReader : public CObserver
{
public:
    CMailReader(const string &strName) : m_strName(strName){}
    virtual void Update(CObservable* pObs, void* pArg = NULL){
            char* pContent = static_cast<char*>(pArg);
            if (dynamic_cast<CBloger*>(pObs)){
                cout << m_strName << " updated from bloger, content: " << pContent << endl;
            }
            if (dynamic_cast<CPortal*>(pObs)){
                cout << m_strName << " updated from portal, content: " << pContent << endl;
            }
        }
private:
    string m_strName;
};

測試用例:

#include "observer.h"
int main()
{
                                  //目標(被觀察者)
    CBloger* pBloger = new CBloger();
    CPortal* pPortal = new CPortal();
                                  //觀察者. 一個觀察者可以觀察多個目標
    CRSSReader* pRssReader = new CRSSReader("rss reader");
    CMailReader* pMailReader = new CMailReader("mail reader");
    pBloger->Attach(pRssReader);  //bloger注冊觀察者
    pBloger->Attach(pMailReader); //bloger注冊觀察者
    pPortal->Attach(pRssReader);  //portal注冊觀察者
    pPortal->Attach(pMailReader); //portal注冊觀察者
                                  
//博客發布信息
    pBloger->Publish("博客分享設計模式");
    cout << endl;
                                  //門戶發布信息
    pPortal->Publish("門戶分享設計模式");
    cout << "\nportal detached mail reader" << endl;
    
    pPortal->Detach(pMailReader);
    
    cout << "portal observers count: " << pPortal->GetObserversCount() << endl << endl;
    pPortal->Publish("門戶分享設計模式");
    
    system("pause");
    return 0;
}