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

            [轉]設計模式-Observer

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

            設計模式-Observer

            1. 解決的問題:

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

            2. 問題分析:

               應該根據數據與現實分離的原則將天氣預報數據和現實形式分別封裝起來,

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

               天氣預報數據發生變化后,需要對所有的顯示形式進行更新.

            3. UML圖與代碼實現:

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

              1: //這個例子中WeatherData就是Subject, 而WeatherView則是Observer,
              2: //這里WeatherView中沒有包含到WeatherData的引用,
              3: //因此這里是Subject用push的方法向Observer發送數據;
              4: //并且注冊和反注冊Observer的時候都是由Subject(WeatherData)執行的
              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數據, 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索取數據;
              4: //并且注冊和反注冊都是Observer自己執行的
              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: }

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

            上面兩種實現的執行結果如下:

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

            5. 總結:

               1. Strategy 模式定義:

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

               2. 體現的設計原則:

            • 將數據與現實分別封裝;
            • 多使用組合,少使用繼承;
            • 面向接口編程,而不面向實現編程;

               3. UML圖:

               4. 要點:

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

            6. 理解:

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

             

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

            精品久久久久久久久免费影院| 国内精品久久人妻互换| 国产一区二区精品久久凹凸 | 亚洲欧美日韩久久精品第一区| 久久精品久久久久观看99水蜜桃| 97久久国产综合精品女不卡| 99久久久精品| 久久久久久午夜精品| 久久人人爽人人爽人人片av高请| av午夜福利一片免费看久久| 久久激情亚洲精品无码?V| 久久综合亚洲欧美成人| 久久久噜噜噜久久中文字幕色伊伊| 成人久久免费网站| 久久久久久亚洲精品不卡| 婷婷伊人久久大香线蕉AV | 亚洲精品国产综合久久一线| 97久久香蕉国产线看观看| 久久精品女人天堂AV麻| 久久精品亚洲精品国产色婷| 亚洲综合久久夜AV | 久久精品国产色蜜蜜麻豆| 精品久久久久久成人AV| 伊人久久精品影院| 久久久久久国产精品无码下载| 久久精品国产亚洲AV无码娇色| 老男人久久青草av高清| 国产精品99久久精品爆乳| 97久久精品国产精品青草| 久久无码人妻一区二区三区 | 久久精品国产只有精品2020| 亚洲AV无码1区2区久久| 久久久亚洲欧洲日产国码是AV| 精品无码久久久久久久动漫| 亚洲国产成人久久综合碰碰动漫3d| 午夜天堂精品久久久久| 亚洲日本va中文字幕久久| 人人妻久久人人澡人人爽人人精品 | 精品久久久久中文字| 色综合久久久久网| 99久久99久久精品国产片果冻|