• <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>

            eryar

            PipeCAD - Plant Piping Design Software.
            RvmTranslator - Translate AVEVA RVM to OBJ, glTF, etc.
            posts - 603, comments - 590, trackbacks - 0, articles - 0

            [轉(zhuǎn)]設計模式-Observer

            Posted on 2012-10-19 22:36 eryar 閱讀(1328) 評論(0)  編輯 收藏 引用

            設計模式-Observer

            1. 解決的問題:

               假如現(xiàn)在要編寫一個天氣預報的公布欄, 公布欄有兩種顯示方式, 一種是圖像方式顯示, 一種是表格形式顯示.

            2. 問題分析:

               應該根據(jù)數(shù)據(jù)與現(xiàn)實分離的原則將天氣預報數(shù)據(jù)和現(xiàn)實形式分別封裝起來,

               今后可能增加其他的顯示形式;

               天氣預報數(shù)據(jù)發(fā)生變化后,需要對所有的顯示形式進行更新.

            3. UML圖與代碼實現(xiàn):

            1)用Push的方式更新Observer數(shù)據(jù), 通過Subject對Observer進行注冊:

              1: //這個例子中WeatherData就是Subject, 而WeatherView則是Observer,
              2: //這里WeatherView中沒有包含到WeatherData的引用,
              3: //因此這里是Subject用push的方法向Observer發(fā)送數(shù)據(jù);
              4: //并且注冊和反注冊Observer的時候都是由Subject(WeatherData)執(zhí)行的
              5: 
              6: #include <iostream>
              7: #include <vector>
              8: #include <algorithm>
              9: 
             10: using namespace std;
             11: 
             12: class WeatherData;
             13: 
             14: class WeatherView
             15: {
             16: public:
             17:     void Update(int temp, int hum)
             18:     {
             19:         temperature = temp;
             20:         humidity = hum;
             21:     };
             22:     virtual void Display()
             23:     {
             24:         cout << "temperature = " << temperature << ", humidity = " << humidity << endl;
             25:     }
             26: 
             27: private:
             28: 
             29:     int temperature;
             30:     int humidity;
             31: };
             32: 
             33: class GraphicView: public WeatherView
             34: {
             35: public:
             36:     void Display()
             37:     {
             38:         cout << "====--Weather Report With Graphic Format--===="<< endl;
             39:         WeatherView::Display();
             40:     }
             41: };
             42: 
             43: class TableView: public WeatherView
             44: {
             45: public:
             46:     void Display()
             47:     {
             48:         cout << "====--Weather Report With Table Format--===="<< endl;
             49:         WeatherView::Display();
             50:     }
             51: };
             52: 
             53: class WeatherData
             54: {
             55: public:
             56:     void SetWeahterData(int temp, int hum)
             57:     {
             58:         temperature = temp;
             59:         humidity = hum;
             60:         NotifyObservcer();
             61:     }
             62: 
             63:     void RegisterObserver(WeatherView* obs)
             64:     {
             65:         obsList.push_back(obs);
             66:     }
             67: 
             68:     void RemoveObserver(WeatherView* obs)
             69:     {
             70:         vector<WeatherView*>::iterator it;
             71:         it = find(obsList.begin(), obsList.end(), obs);
             72:         if (it != obsList.end())
             73:             obsList.erase(it);
             74:     }
             75: 
             76: private:
             77:     vector<WeatherView*> obsList;
             78:     int temperature;
             79:     int humidity;
             80:     void NotifyObservcer()
             81:     {
             82:        vector<WeatherView*>::iterator it;
             83:        for(it = obsList.begin(); it < obsList.end(); it++)
             84:        {
             85:            (*it)->Update(temperature, humidity);
             86:        }
             87:     }
             88: };
             89: 
             90: 
             91: int main()
             92: {
             93:     WeatherData *wd = new WeatherData();
             94:     GraphicView *gv = new GraphicView();
             95:     TableView *tv = new TableView();
             96: 
             97:     wd->RegisterObserver(gv);
             98:     wd->RegisterObserver(tv);
             99:     wd->SetWeahterData(23,45);
            100:     gv->Display();
            101:     tv->Display();
            102: 
            103:     wd->RemoveObserver(gv);
            104:     wd->SetWeahterData(67,89);
            105:     gv->Display();
            106:     tv->Display();
            107: 
            108:     return 0;
            109: }
            2)用Pull的方式更新Observer數(shù)據(jù), Observer自己進行注冊:

              1: #ifndef WEATHERDATA_HPP_INCLUDED
              2: #define WEATHERDATA_HPP_INCLUDED
              3: #include <iostream>
              4: #include <vector>
              5: 
              6: #include "WeatherView.hpp"
              7: 
              8: class WeatherData
              9: {
             10: public:
             11:     void SetWeahterData(int temp, int hum)
             12:     {
             13:         temperature = temp;
             14:         humidity = hum;
             15:         NotifyObservcer();
             16:     }
             17: 
             18:     int GetTemperature()
             19:     {
             20:         return temperature;
             21:     }
             22: 
             23:     int GetHumidty()
             24:     {
             25:         return humidity;
             26:     }
             27: 
             28:     void RegisterObserver(WeatherView* obs);
             29:     void RemoveObserver(WeatherView* obs);
             30: 
             31: private:
             32:     vector<WeatherView*> obsList;
             33:     int temperature;
             34:     int humidity;
             35:     void NotifyObservcer();
             36: };
             37: 
             38: #endif

            =================

              1: #ifndef WEATHERVIEW_HPP_INCLUDED
              2: #define WEATHERVIEW_HPP_INCLUDED
              3: 
              4: #include <iostream>
              5: #include <vector>
              6: #include <algorithm>
              7: 
              8: 
              9: class WeatherData;
             10: 
             11: using namespace std;
             12: 
             13: class WeatherView
             14: {
             15: public:
             16:     WeatherView(WeatherData* wd);
             17: 
             18:     void Update();
             19:     void Register();
             20:     void Unregister();
             21: 
             22:     virtual void Display()
             23:     {
             24:         cout << "temperature = " << temperature << ", humidity = " << humidity << endl;
             25:     }
             26: 
             27: private:
             28:     WeatherData* wd;
             29:     int temperature;
             30:     int humidity;
             31: };
             32: 
             33: class GraphicView: public WeatherView
             34: {
             35: public:
             36:     GraphicView(WeatherData* wd);
             37:     void Display()
             38:     {
             39:         cout << "====--Weather Report With Graphic Format--===="<< endl;
             40:         WeatherView::Display();
             41:     }
             42: };
             43: 
             44: class TableView: public WeatherView
             45: {
             46: public:
             47:     TableView(WeatherData* wd);
             48:     void Display()
             49:     {
             50:         cout << "====--Weather Report With Table Format--===="<< endl;
             51:         WeatherView::Display();
             52:     }
             53: };
             54: 
             55: #endif

            ===================

              1: //這個例子中WeatherData就是Subject, 而WeatherView則是Observer,
              2: //這里WeatherView中有一個包含到WeatherData的指針,
              3: //因此這里是Observer用pull的方法主動向Observer索取數(shù)據(jù);
              4: //并且注冊和反注冊都是Observer自己執(zhí)行的
              5: #include <iostream>
              6: #include <vector>
              7: #include <algorithm>
              8: #include "WeatherView.hpp"
              9: #include "WeatherData.hpp"
             10: 
             11: void WeatherData::RegisterObserver(WeatherView* obs)
             12: {
             13:     obsList.push_back(obs);
             14: }
             15: 
             16: void WeatherData::RemoveObserver(WeatherView* obs)
             17: {
             18:     vector<WeatherView*>::iterator it;
             19:     it = find(obsList.begin(), obsList.end(), obs);
             20:     if (it != obsList.end())
             21:         obsList.erase(it);
             22: }
             23: 
             24: void WeatherData::NotifyObservcer()
             25: {
             26:    vector<WeatherView*>::iterator it;
             27:    for(it = obsList.begin(); it < obsList.end(); it++)
             28:    {
             29:        (*it)->Update();
             30:    }
             31: }
             32: 
             33: 
             34: WeatherView::WeatherView(WeatherData* pwd)
             35: {
             36:     wd = pwd;
             37: }
             38: 
             39: void WeatherView::Update()
             40: {
             41:     temperature = wd->GetTemperature();
             42:     humidity = wd->GetHumidty();
             43: };
             44: 
             45: void WeatherView::Register()
             46: {
             47:     wd->RegisterObserver(this);
             48: };
             49: 
             50: void WeatherView::Unregister()
             51: {
             52:     wd->RemoveObserver(this);
             53: };
             54: 
             55: GraphicView::GraphicView(WeatherData* pwd) : WeatherView(pwd)
             56: {
             57: 
             58: }
             59: 
             60: TableView::TableView(WeatherData* pwd) : WeatherView(pwd)
             61: {
             62: 
             63: }
             64: int main()
             65: {
             66:     WeatherData *wd = new WeatherData();
             67:     GraphicView *gv = new GraphicView(wd);
             68:     gv->Register();
             69:     TableView *tv = new TableView(wd);
             70:     tv->Register();
             71: 
             72:     wd->SetWeahterData(23,45);
             73:     gv->Display();
             74:     tv->Display();
             75: 
             76:     gv->Unregister();
             77:     wd->SetWeahterData(67,89);
             78:     gv->Display();
             79:     tv->Display();
             80: 
             81:     return 0;
             82: }

            ======================

            上面兩種實現(xiàn)的執(zhí)行結(jié)果如下:

              1: ====--Weather Report With Graphic Format--====  
            
              2: temperature = 23, humidity = 45  
            
              3: ====--Weather Report With Table Format--====  
            
              4: temperature = 23, humidity = 45  
            
              5: ====--Weather Report With Graphic Format--====  
            
              6: temperature = 23, humidity = 45  
            
              7: ====--Weather Report With Table Format--====  
            
              8: temperature = 67, humidity = 89  

            4. Push還是Pull?

            對于上面的例子, Observer中的數(shù)據(jù)是從Subject中一次性全部更新的(temperature 和 humidity), 這種更新數(shù)據(jù)的方式便是push;然而如果WeatherData中的數(shù)據(jù)量非常大, 而有些Observer并不需要所有的數(shù)據(jù), 比如現(xiàn)在要新增兩個顯示方式,一個是只顯示溫度,而另一個則只顯示濕度, 這樣的話就沒有必要讓所有的Observer都得到所有的數(shù)據(jù). 最好的方式是Observer能根據(jù)自己的需要從Subject中去取得數(shù)據(jù),這種更新數(shù)據(jù)的方式便是Pull. Observer模式中Push和Pull兩種設計方法體現(xiàn)在具體的程序中就是Observer中的Update()接口參數(shù)不同, 對于Push模式, Update()接口的參數(shù)通常就是需要Push的那些數(shù)據(jù),比如這里的溫度和濕度; 對于Pull模式, Update()的參數(shù)是Subject的一個引用, 然后Subject提供一些數(shù)據(jù)接口,由Observer通過這些接口自己取得所需要的數(shù)據(jù).

            5. 總結(jié):

               1. Strategy 模式定義:

                  定義對象間的一種一對多的依賴關系,當一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并被自動更新.

               2. 體現(xiàn)的設計原則:

            • 將數(shù)據(jù)與現(xiàn)實分別封裝;
            • 多使用組合,少使用繼承;
            • 面向接口編程,而不面向?qū)崿F(xiàn)編程;

               3. UML圖:

               4. 要點:

            • Strategy 基類需要定義出可供Client使用的一些算法接口;
            • 可以隨時根據(jù)需要增加 Strategy 而不會影響到Client;
            • Client 里面需要包含對 Strategy 的引用;
            • Client 可以隨時更換 Strategy;

            6. 理解:

            • Observer模式是解決對象之間數(shù)據(jù)傳遞問題的一種模式;
            • Observer的注冊可以由Subject執(zhí)行也可以由Observer自己執(zhí)行;
            • 和Strategy模式的比較:
              1) Observer模式中Observer 中定義了 Update()接口供 Subject調(diào)用; 而Strategy模式中,Strategy定義了AlgrithmInterface()供Client調(diào)用;
              2) Observer模式中Subject和Observer是一對多的關系, 因此Subject是一次調(diào)用n個Observer的Update()接口;而Strategy模式中Client與Strategy之間是一對一的關系, Client 就是調(diào)用指定的那個Strategy的AlgrithmInterface();
              3) 也正因為這種對應關系的不同, 在Observer模式中, Subject可以Register或者Remove某個Observer, 而Strategy模式中通常只是set某個Strategy

             

            原文地址: http://blog.csdn.net/zhongjiekangping/article/details/6903017

            亚洲国产精品久久久久网站| 久久精品免费一区二区| 久久国产精品国语对白| 亚洲国产成人乱码精品女人久久久不卡 | 久久久久久久精品成人热色戒| 午夜精品久久久久久99热| 99久久国产综合精品成人影院| 人妻无码精品久久亚瑟影视| 亚洲精品国产美女久久久| 久久精品国产99久久丝袜| 香蕉久久av一区二区三区| 国内精品伊人久久久久网站| 久久久久99精品成人片欧美 | 伊人久久精品无码av一区| 日韩欧美亚洲综合久久影院d3| 亚洲欧美另类日本久久国产真实乱对白| 精品久久久久久无码中文字幕一区| 久久精品国产色蜜蜜麻豆| 精品国产VA久久久久久久冰| 久久人人爽人人人人爽AV| 国产精品久久久久久久久久免费| 久久久精品国产sm调教网站| 国产精品乱码久久久久久软件| AAA级久久久精品无码区| 狠狠狠色丁香婷婷综合久久五月| 国产精品99久久久久久宅男小说| 久久精品无码一区二区app| 99久久99久久精品国产| 久久亚洲高清观看| 狠狠色丁香婷婷综合久久来 | 久久国产免费观看精品| 久久综合给合久久国产免费| 久久精品国产乱子伦| 亚洲精品无码久久久久AV麻豆| 欧美性大战久久久久久| 久久久久久亚洲精品无码| 久久亚洲国产成人影院网站| 日韩亚洲国产综合久久久| 亚洲精品美女久久久久99小说| 亚洲人成无码网站久久99热国产| 亚洲精品无码久久不卡|