成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

設(shè)計者模式(1)觀察者模式(Observer)C++11實(shí)現(xiàn)-創(chuàng)新互聯(lián)

意圖

觀察者模式(Observer),又叫發(fā)布-訂閱模式(Publish/Subscribe),定義對象間一種一對多的依賴關(guān)系,使得每當(dāng)一個對象改變狀態(tài),則所有依賴于它的對象都會得到通知并自動更新。
該模式屬于行為型模式。

創(chuàng)新互聯(lián)為您提適合企業(yè)的網(wǎng)站設(shè)計?讓您的網(wǎng)站在搜索引擎具有高度排名,讓您的網(wǎng)站具備超強(qiáng)的網(wǎng)絡(luò)競爭力!結(jié)合企業(yè)自身,進(jìn)行網(wǎng)站設(shè)計及把握,最后結(jié)合企業(yè)文化和具體宗旨等,才能創(chuàng)作出一份性化解決方案。從網(wǎng)站策劃到成都網(wǎng)站制作、網(wǎng)站設(shè)計, 我們的網(wǎng)頁設(shè)計師為您提供的解決方案。參與者
  • Subject:抽象主題(抽象被觀察者),抽象主題角色把所有觀察者對象保存在一個集合里,每個主題都可以有任意數(shù)量的觀察者,抽象主題提供一個或者多個接口,可以增加和刪除觀察者對象。
  • ConcreteSubject:具體主題(具體被觀察者),該角色將有關(guān)狀態(tài)存入具體觀察者對象,在具體主題的內(nèi)部狀態(tài)發(fā)生改變時,給所有注冊過的觀察者發(fā)送通知。
  • Observer:抽象觀察者,是觀察者者的抽象類,它定義了一個或者多個更新接口,使得在得到主題更改通知時更新自己。
  • ConcreteObserver:具體觀察者,實(shí)現(xiàn)抽象觀察者定義的更新接口,以便在得到主題更改通知時更新自身的狀態(tài)。
優(yōu)點(diǎn)
  • 觀察者模式可以實(shí)現(xiàn)表示層和數(shù)據(jù)邏輯層的分離,抽象了更新接口,使得可以有各種各樣不同的表示層作為具體觀察者角色
  • 觀察者模式在觀察目標(biāo)和觀察者之間建立一個抽象的耦合
  • 觀察者模式支持廣播通信
缺點(diǎn)
  • 在應(yīng)用觀察者模式時需要考慮一下開發(fā)效率和運(yùn)行效率的問題,程序中包括一個被觀察者、多個觀察者,將所有的觀察者都通知到會花費(fèi)很多時間。如果考慮到性能問題,可以實(shí)現(xiàn)一個異步非阻塞的觀察者模式,在每次fire subject的時候創(chuàng)建一個新的線程執(zhí)行代碼。

  • 觀察者模式?jīng)]有相應(yīng)的機(jī)制讓觀察者知道所觀察的目標(biāo)對象是怎么發(fā)生變化的,而僅僅只是知道觀察目標(biāo)發(fā)生了變化。

代碼實(shí)現(xiàn)
#include#include#include#include#includeclass Observer;
typedef std::vector>::iterator Iterator;//迭代器

//抽象被觀察者
class Subject
{public:
    virtual void Attach(std::weak_ptr)=0;//注冊觀察者對象的接口
    virtual Iterator Detach(Iterator it)=0;//刪除觀察者對象的接口
    virtual void notifyObservers()=0;//告知所有觀察者update
};

//抽象觀察者

class Observer
{public:
    virtual void update()=0;//更新自身狀態(tài)
};

//被觀察者
class ConcreteSubject :public::Subject
{public:
    void Attach(std::weak_ptrs)
    {//vector的add是線程安全的
        observers_.push_back(s);
    }
    Iterator Detach(Iterator it)
    {//線程不安全,要在臨界區(qū)調(diào)用此接口
        return observers_.erase(it);
    }

    void notifyObservers()
    {lock.lock();
        Iterator it=observers_.begin();
        while(it!=observers_.end())
        {//先嘗試將weak_ptr提升為share_ptr
            std::shared_ptrobj=it->lock();
            if(obj)//提升成功,說明該對象未被其他線程析構(gòu)
            {obj->update();//更新
                ++it;
            }
            else//提升失敗,說明該對象已被其他線程析構(gòu)
            {//從觀察者集合中將已被析構(gòu)對象刪除
                //因?yàn)榇颂帉儆谂R界區(qū),是線程安全的
                it=Detach(it);
            }

        }
        lock.unlock();
    }
    
private:
    mutable std::mutex lock;
    std::vector>observers_;//觀察者集合

};

//觀察者按需求定義即可,需要繼承抽象觀察者
//以下為例
class Teacher :public::Observer
{public:
    void update()
    {std::cout<<"Teacher is update"<std::cout<<"Teacher is ~"<public:
    void update()
    {std::cout<<"Student is update"<std::cout<<"Student is ~"<

測試

int main()
{ConcreteSubject subject;
    
    std::shared_ptrteacher(new Teacher);
    subject.Attach(teacher);
    {std::shared_ptrstudent(new Student);
        subject.Attach(student);
        subject.notifyObservers();
    }


    subject.notifyObservers();

}

執(zhí)行結(jié)果

Teacher is update
Student is update
Student is ~
Teacher is update
Teacher is ~
迭代器失效問題分析

在學(xué)習(xí)該模型時,遇到了一個bug,問題鎖定在notifyObservers()當(dāng)中,當(dāng)時的實(shí)現(xiàn)如下

void notifyObservers()
{lock.lock();
    Iterator it=observers_.begin();
    while(it!=observers_.end())
    {std::shared_ptrobj=it->lock();
        if(obj)
        {obj->update();
        }
        else
        {Detach(it);
        }
        it++;
    }
}

當(dāng)時執(zhí)行main時,就會報段錯誤,經(jīng)過檢查不難發(fā)現(xiàn),問題是迭代器失效了

刪除導(dǎo)致迭代器失效

這個問題其實(shí)很好分析,在一順序容器當(dāng)中(vector,queue…等),數(shù)據(jù)是順序存儲的,當(dāng)刪除一個元素后,內(nèi)存中的數(shù)據(jù)會往前移動,以保證數(shù)據(jù)的緊湊。所以刪除一個元素后,該元素后面的其他元素的地址都會發(fā)生改變。在刪除操作前所持有的迭代器就會有失效的可能??聪旅娴睦?。

#include#include#includeusing namespace std;
int main()
{  vectorarr;
  arr.push_back(1);
  arr.push_back(2);
  arr.push_back(3);
  arr.push_back(4);
  arr.push_back(5);

  vector::iterator it=arr.begin()+3;

  cout<<"刪除操作前該迭代器所指向的元素:"<

執(zhí)行結(jié)果如下

刪除操作前該迭代器所指向的元素:
4
進(jìn)行刪除操作
刪除操作前該迭代器所指向的元素:
5
添加導(dǎo)致迭代器失效

你的添加的操作也是可能導(dǎo)致迭代器失效的。vector的容量是動態(tài)的開辟的,當(dāng)容量不夠的話,會進(jìn)行realloc操作進(jìn)行擴(kuò)容,若該數(shù)組的后面的空間不足,realloc函數(shù)會找一片更大的空間,將原數(shù)據(jù)拷貝進(jìn)去。若在此事件發(fā)生前,獲取一個迭代器,此事件發(fā)生后,該迭代器會失效??聪旅胬?/p>

#include#include#includeusing namespace std;
int main()
{  vectorarr;
  arr.push_back(1);
  arr.push_back(2);
  arr.push_back(3);
  arr.push_back(4);
  arr.push_back(5);

  vector::iterator it=arr.begin()+3;

  cout<<"此事件發(fā)生前該迭代器所指向的元素:"<arr.push_back(9);
  }
  cout<<"此事件發(fā)生后該迭代器所指向的元素:"<

執(zhí)行結(jié)果

此事件發(fā)生前該迭代器所指向的元素:
4
此事件發(fā)生后該迭代器所指向的元素:
21854

此時該迭代器就指向一個未初始化的空間

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

當(dāng)前標(biāo)題:設(shè)計者模式(1)觀察者模式(Observer)C++11實(shí)現(xiàn)-創(chuàng)新互聯(lián)
文章位置:http://jinyejixie.com/article26/djhccg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司商城網(wǎng)站、App設(shè)計、標(biāo)簽優(yōu)化、手機(jī)網(wǎng)站建設(shè)ChatGPT

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

阿巴嘎旗| 曲麻莱县| 文昌市| 托克逊县| 丹江口市| 丹江口市| 徐州市| 永昌县| 吉首市| 蒙城县| 宁武县| 凤山县| 安达市| 松潘县| 淮北市| 梓潼县| 江城| 杭州市| 天等县| 西吉县| 北票市| 江津市| 塔城市| 岫岩| 呼伦贝尔市| 印江| 武清区| 山西省| 盱眙县| 霍山县| 颍上县| 包头市| 金平| 涿州市| 新平| 北辰区| 高要市| 兖州市| 双鸭山市| 繁昌县| 锡林郭勒盟|