觀察者模式(observer)c++實現

來源:互聯網
上載者:User

標籤:

1意圖

定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。

2別名

依賴(Dependents), 發布-訂閱(Publish-Subscribe)

3動機

將一個系統分割成一系列相互協作的類有一個常見的副作用:需要維護相關對象間的一致性。我們不希望為了維持一致性而使各類緊密耦合,因為這樣降低了他們的可重用性。

4實用性

1、當一個抽象模型有兩個方面,其中一個方面依賴於另一個方面。將二者封裝在獨立的對象中以使他們可以各自獨立的改變和複用。

2、當對一個對象的改變需要同時改變其它對象,而不知道具體有多少對象待改變。

3、當一個對象必須通知其它對象,而它又不能假定其它對象是誰。換言之,你不希望這些對象是緊密耦合的。

5結構

 

7優缺點

1、使目標和觀察者之間的耦合是抽象的最小的。

2、支援廣播通訊

3、意外的更新    因為一個觀察者並不知道其它觀察者的存在,它可能對改變目標的最終代價一無所知。在目標上一個看視無害的操作可能會引起一系列對觀察者以及依賴這些觀察者的那些對象的更新。此外,如果依賴準則的定義或維護不當,常常會引起錯誤的更新,這種錯誤通常很難補捉。

--以上內容來自《可複用面向對向軟體的基礎》

 

代碼執行個體:

本例子簡單的類比車輛運行和紅綠燈的關係。例子中實現了一個Signallamp的基類(observer),凡是繼承這個基類的類都可以觀察紅綠燈資訊,並讓(concreteObserver)類Vehicle,繼承Signallamp。實現了一個subject的基類,凡是繼承subject的concretesubject都可以被繼承Signallamp的具體觀察者觀察,並實現子類TrafficSignal。

在用戶端我們實現了幾輛車在運行,當紅綠燈變化時,有觀察紅綠燈的車將收影響。所以:

這裡圖片沒有說明什麼,但可以方便我們想象到用戶端情境。許多車在不斷的移動,當變成紅燈的時候,那些觀察TrafficSignal事件的車輛將停止移動,而沒有觀察該事件的車將不受影響。

1、observer.h中代碼如下:

#ifndef _OBSERVER_#define _OBSERVER_#include <iostream>using namespace std;void gotoxy(int x,int y);enum Signallamp{RedSignal, GreenSignal};class ObserverTrafficSignal{public:    ObserverTrafficSignal(){}    virtual void updataSignal(Signallamp signal) = 0;};class Vehicle: public ObserverTrafficSignal{public:    Vehicle(int px, int py):_pointx(px), _pointy(py){isRed = false;}    void drawVehicle();    void clearVehicle();    void updataposition();    void setmovestep(int stepx, int stepy);    virtual void updataSignal(Signallamp signal);private:    int _pointx;    int _pointy;    int _move_x;    int _move_y;    int _save_movex;    int _save_movey;    bool isRed;};#endif
observer.h

2、observer.cpp中的代碼如下:

#include "observer.h"#include <iostream>using namespace std;#include<windows.h>void gotoxy(int x,int y){    COORD coord={x,y};    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);}void conceal_cursor(){    CONSOLE_CURSOR_INFO cci;    cci.bVisible = false;    cci.dwSize = sizeof(cci);    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);    SetConsoleCursorInfo(handle, &cci);}void Vehicle::drawVehicle(){    //conceal_cursor();    int i=0;    gotoxy(_pointx, _pointy+(i++));    cout<<" __________________";    gotoxy(_pointx, _pointy+(i++));    cout<<"|                  |";    gotoxy(_pointx, _pointy+(i++));    cout<<"|[_][_][_][_][_][_]|";    gotoxy(_pointx, _pointy+(i++));    cout<<"|o _         _  _  |";    gotoxy(_pointx, _pointy+(i++));    cout<<" `(_)-------(_)(_)-\"";}void Vehicle::clearVehicle(){    int i=0;    gotoxy(_pointx, _pointy+(i++));    cout<<"                    ";    gotoxy(_pointx, _pointy+(i++));    cout<<"                    ";    gotoxy(_pointx, _pointy+(i++));    cout<<"                    ";    gotoxy(_pointx, _pointy+(i++));    cout<<"                    ";    gotoxy(_pointx, _pointy+(i++));    cout<<"                    ";}void Vehicle::updataposition(){    _pointx += _move_x;    _pointy += _move_y;    if(_pointx > 80 )        _pointx = 1;    if(_pointy>50)        _pointy = 1;    if(_pointy<1)        _pointy = 50;    if(_pointx<1)        _pointx = 80;}void Vehicle::setmovestep(int stepx, int stepy){    _move_x = stepx;        _move_y = stepy;    }void Vehicle::updataSignal(Signallamp signal){    switch(signal)    {    case RedSignal:        if(!isRed)        {            isRed = true;            _save_movex = _move_x;            _save_movey = _move_y;            setmovestep(0, 0);        }        break;    case GreenSignal:        if(isRed)        {            setmovestep(_save_movex, _save_movey);            isRed = false;        }        break;    }}
observer.cpp

代碼中updataSignal函數在遇見紅燈時,用_save_movex和_save_movey儲存了車子原始的移動速度,以便變成綠燈時恢複。

3、subject.h中的代碼如下:

#ifndef _SUBJECT_#define _SUBJECT_#include <list>using std::list;#include "observer.h"class subject{public:    subject(){}    virtual void attach(ObserverTrafficSignal* ob);    virtual void detach(ObserverTrafficSignal* ob);    virtual void notify() = 0;    list<ObserverTrafficSignal* > _observers;};class TrafficSignal:public subject{public:    TrafficSignal():_countTime(8),_signal(GreenSignal){}    virtual void notify();private:    int _countTime;    Signallamp _signal;};#endif
subject.h

4、subject.cpp中的代碼如下:

#include "subject.h"#include<iostream>#include <iterator>using std::iterator;void subject::attach(ObserverTrafficSignal* ob){    if(NULL != ob)        _observers.push_back(ob);}void subject::detach(ObserverTrafficSignal* ob){    if(NULL != ob)        _observers.remove(ob);}void TrafficSignal::notify(){    if(!_countTime)    {        _countTime = rand()%5 + 4;        ;        if(_signal == RedSignal)            _signal = GreenSignal;        else            _signal = RedSignal;    }    _countTime--;    gotoxy(30, 4);    if(_signal == RedSignal)        std::cout<<"--紅燈--";    else        std::cout<<"--綠色--";    list<ObserverTrafficSignal* >::iterator iter = _observers.begin();    for(iter; iter != _observers.end(); iter++)    {        (*iter)->updataSignal(_signal);    }}
subject.cpp

代碼中notify函數通過隨即一個數_countTime的簡單的類比了紅綠燈(只有紅燈和綠燈),每一次運行將_countTime減一,當_countTime等於零時再次隨即一個數,並更好紅綠燈。

5、main.cpp中的代碼如下:

#include <iostream>using namespace std;#include <time.h>#include "subject.h"int main(){    srand(time(0));    Vehicle ve1(80, 5);    ve1.setmovestep(-3, 0);    Vehicle ve2(80, 12);    ve2.setmovestep(-4, 0);    Vehicle ve3(80, 20);    ve3.setmovestep(-2, 0);    TrafficSignal tra;    tra.attach(&ve1);    //tra.attach(&ve2);    tra.attach(&ve3);    while(1)    {        ve1.drawVehicle();        ve2.drawVehicle();        ve3.drawVehicle();        _sleep(200);        ve1.clearVehicle();        ve2.clearVehicle();        ve3.clearVehicle();        ve1.updataposition();        ve2.updataposition();        ve3.updataposition();        tra.notify();    }    return 0;}

 

 

觀察者模式(observer)c++實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.