• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            設(shè)計(jì)模式之觀察者模式

            一、什么是觀察者模式

                 Observer模式也叫觀察者模式,是由GoF提出的23種軟件設(shè)計(jì)模式的一種。Observer模式是行為模式之一,它的作用是當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生變化時(shí),能夠自動(dòng)通知其他關(guān)聯(lián)對(duì)象,自動(dòng)刷新對(duì)象狀態(tài)。

              觀察者模式(Observer)完美的將觀察者和被觀察的對(duì)象分離開。舉個(gè)例子,用戶界面可以作為一個(gè)觀察者,業(yè)務(wù)數(shù)據(jù)是被觀察者,用戶界面觀察業(yè)務(wù)數(shù)據(jù)的變化,發(fā)現(xiàn)數(shù)據(jù)變化后,就顯示在界面上。面向?qū)ο笤O(shè)計(jì)的一個(gè)原則是:系統(tǒng)中的每個(gè)類將重點(diǎn)放在某一個(gè)功能上,而不是其他方面。一個(gè)對(duì)象只做一件事情,并且將他做好。觀察者模式在模塊之間劃定了清晰的界限,提高了應(yīng)用程序的可維護(hù)性和重用性。

             

              觀察者模式有很多實(shí)現(xiàn)方式,從根本上說(shuō),該模式必須包含兩個(gè)角色:觀察者和被觀察對(duì)象。在剛才的例子中,業(yè)務(wù)數(shù)據(jù)是被觀察對(duì)象,用戶界面是觀察者。觀察者和被觀察者之間存在“觀察”的邏輯關(guān)聯(lián),當(dāng)被觀察者發(fā)生改變的時(shí)候,觀察者就會(huì)觀察到這樣的變化,并且做出相應(yīng)的響應(yīng)。如果在用戶界面、業(yè)務(wù)數(shù)據(jù)之間使用這樣的觀察過程,可以確保界面和數(shù)據(jù)之間劃清界限,假定應(yīng)用程序的需求發(fā)生變化,需要修改界面的表現(xiàn),只需要重新構(gòu)建一個(gè)用戶界面,業(yè)務(wù)數(shù)據(jù)不需要發(fā)生變化。

             

              “觀察”不是“直接調(diào)用”

              實(shí)現(xiàn)觀察者模式的時(shí)候要注意,觀察者和被觀察對(duì)象之間的互動(dòng)關(guān)系不能體現(xiàn)成類之間的直接調(diào)用,否則就將使觀察者和被觀察對(duì)象之間緊密的耦合起來(lái),從根本上違反面向?qū)ο蟮脑O(shè)計(jì)的原則。無(wú)論是觀察者“觀察”觀察對(duì)象,還是被觀察者將自己的改變“通知”觀察者,都不應(yīng)該直接調(diào)用。

             

              實(shí)現(xiàn)觀察者模式的形式

              實(shí)現(xiàn)觀察者模式有很多形式,比較直觀的一種是使用一種“注冊(cè)——通知——撤銷注冊(cè)”的形式。

             

               實(shí)現(xiàn)觀察者模式例子

                   下面是C++的實(shí)現(xiàn),在C++實(shí)現(xiàn)中,C++中沒有接口的概念,但是可以用抽象類類代替Java或C#中的接口,在C++中抽象類中從派生類中抽象出來(lái)的函數(shù)(方法),必須定義成純虛函數(shù),這樣在后面的使用中才可以通過基類的指針來(lái)訪問這些函數(shù),面向?qū)ο蟮恼Z(yǔ)言中有個(gè)特點(diǎn),多態(tài)只能訪問兩者中共有的部分。

              1
              2#include "stdafx.h"
              3#include <string>
              4#include <vector>
              5#include<list>
              6#include<iostream>
              7using namespace std;
              8
              9class Observer;
             10class Subject
             11{
             12public:
             13    //注冊(cè)
             14     virtual void attach(Observer *o)=0;
             15     //撤銷
             16     virtual void dettach(Observer *o)=0;
             17     //發(fā)送消息,更新觀察者數(shù)據(jù)
             18     virtual void change()=0;
             19     //更新數(shù)據(jù)
             20     virtual void setWeather(string str)=0;
             21     //獲取數(shù)據(jù)
             22     virtual string getWeather()=0;
             23}
            ;
             24
             25class Observer
             26{
             27public:
             28    //獲得觀察者的名字,用于后面dettach撤銷操作
             29     virtual string getName()=0;
             30     //更新數(shù)據(jù),用于被觀察者調(diào)用
             31     virtual void update(Subject *s)=0;
             32}
            ;
             33
             34//被觀察者
             35class Earth: public Subject
             36{
             37private:
             38    //數(shù)據(jù)
             39     string weather;
             40     //存放觀察者的list,因?yàn)镺bserver是個(gè)抽象類,
             41     //所以不能聲明成 list<Observer >* l
             42     list<Observer* >* l;//指針 
             43public:
             44    //初始化存放觀察者的容器
             45     Earth()
             46     {
             47        l = new list<Observer*>;
             48     }
            ;
             49     //別忘了釋放資源
             50    ~Earth()
             51    {
             52        delete l;
             53    }
            ;
             54    //注冊(cè)觀察者
             55     void attach(Observer *o)
             56     {
             57        this->l->push_back(o);
             58     }
            ;
             59    
             60     //注銷觀察者
             61      void dettach(Observer *o)
             62     {
             63         for(list<Observer*>::iterator it=l->begin();it!=l->end();++it)
             64         {
             65             //通過string來(lái)進(jìn)行查找,其他通過指針怎么判斷相等比較困難
             66             if( (*it)->getName() == o->getName())
             67             {
             68                 l->remove(*it);
             69                 break;
             70             }

             71         }

             72     }
            ;
             73
             74    //通知并更新觀察者
             75     void change()
             76     {
             77          for(list<Observer*>::iterator it=l->begin();it!=l->end();++it)
             78          {
             79            (*it)->update(this);
             80          }

             81     }
            ;
             82
             83     //更新數(shù)據(jù)
             84     void setWeather(string str)
             85     {
             86          this->weather=str;
             87          change();
             88     }
            ;
             89
             90     string getWeather()
             91     {
             92         return this->weather;
             93     }
            ;
             94
             95}
            ;
             96
             97class Satellite:public Observer
             98{
             99private:
            100     string name;
            101public:
            102     Satellite(string str)
            103     {
            104          name=str;
            105     }

            106     string getName()
            107     {
            108         return name;
            109     }
            ;
            110     //更新數(shù)據(jù)
            111     void update(Subject *s)
            112     {
            113         cout<<this->getName()+" "+s->getWeather()<<endl;
            114     }

            115}
            ;
            116
            117
            118
            119int _tmain(int argc, _TCHAR* argv[])
            120{
            121     Earth e;
            122     Satellite *s1 = new Satellite("風(fēng)云一號(hào)");
            123     Satellite *s2 = new Satellite("風(fēng)云二號(hào)");
            124     Satellite *s3 = new Satellite("風(fēng)云三號(hào)");
            125     Satellite *s4 = new Satellite("風(fēng)云四號(hào)");
            126     e.attach(s1);
            127     e.attach(s2);
            128     e.attach(s3);
            129     e.attach(s4);
            130     e.setWeather("fine");
            131     e.setWeather("rain");
            132     //注銷s3
            133     e.dettach(s3);
            134     e.setWeather("fine");
            135     e.setWeather("rain");
            136
            137
            138    return 0;
            139}

            140
            141

            以上文字參照http://blog.csdn.net/preciousboy/article/details/6230467,對(duì)其代碼進(jìn)行修改在vs2008中編譯調(diào)試通過。
            結(jié)果運(yùn)行為:


            這里要注意的幾個(gè)問題是?
            1.被觀察者怎么去通知觀察者數(shù)據(jù)已經(jīng)更新?--本例子中是通過void change()函數(shù)來(lái)實(shí)現(xiàn)的;
            2.在此模式中你可以從被觀察者處push或者pull數(shù)據(jù),我們認(rèn)為push的方式是正確的。
            3.觀察者模式定義了一對(duì)多的關(guān)系
            4.有多個(gè)觀察者時(shí)不依賴于特定的通知次序。
            5.java的MVC模式就采用此模式實(shí)現(xiàn)。

            posted on 2012-05-01 11:47 sheng 閱讀(645) 評(píng)論(0)  編輯 收藏 引用


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            導(dǎo)航

            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            統(tǒng)計(jì)

            常用鏈接

            留言簿(1)

            隨筆檔案

            收藏夾

            同行

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            精品久久久久久无码免费| 精品久久久久中文字| 久久久久亚洲AV无码专区网站| 久久久久无码精品国产不卡| 久久亚洲sm情趣捆绑调教| 久久人人爽人人澡人人高潮AV| 色综合久久中文色婷婷| 狠狠色婷婷综合天天久久丁香| 国内精品久久久久伊人av| 国产精品国色综合久久| 天天躁日日躁狠狠久久| 一本色综合网久久| 亚洲av伊人久久综合密臀性色| 2019久久久高清456| 7777精品久久久大香线蕉| 久久久噜噜噜久久中文字幕色伊伊 | 国产精品亚洲综合久久| 热RE99久久精品国产66热| 老司机午夜网站国内精品久久久久久久久 | 亚洲国产精品一区二区三区久久 | 好久久免费视频高清| 久久99国产精品久久| 久久艹国产| 久久只有这里有精品4| 综合久久国产九一剧情麻豆| 一本一本久久aa综合精品| jizzjizz国产精品久久| 亚洲国产精品无码久久久久久曰| 久久亚洲sm情趣捆绑调教| 激情伊人五月天久久综合| 国产精品日韩深夜福利久久 | 奇米综合四色77777久久| 国产91色综合久久免费分享| 国产无套内射久久久国产| 午夜精品久久久久久久无码| 无码人妻久久一区二区三区免费丨 | 久久精品一区二区影院| 狠狠色丁香久久婷婷综合| 精品亚洲综合久久中文字幕| 亚洲精品无码久久毛片| 国产91久久精品一区二区|