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

            The Programming world of Alex

            設計模式之Observer模式

            引例:
            銀行現在的業務大多有提醒業務,比如我們用信用卡消費的時候銀行會有短信通知和Email通知等方法立即提醒客戶賬戶發生了變化。這就是典型的Observer模式,A(賬戶)發生變化之后通知B(手機)和C(Email),以后也許還會通知D(電話)等等。。。

            程序設計中也會遇到很多這樣的問題,比如說MFC中的Document/View架構,Document中的數據變化會立即通知View的顯示也相應變化,View的顯示變化后也會通知Document中的數據產生對應變化;再比如回調函數,觸發某個事件后通知調用回調函數。但凡“通知依賴”問題大都可以用到Observer模式。

            動機:
            為某些對象建立“通知依賴關系”——“一個對象的狀態發生改變,那么與之相關的所有對象都要改變”。
            顯然這種關系是緊耦合的,為保證這種結構在遇到變化時能夠比較穩定,我們必須使之松耦合。

            意圖:
            定義對象間的一種一對多關系,以便當一個對象的狀態發生改變時,所有依賴它的對象都得到通知和自動更新(GoF23)

            設計思路:
            我們的目的是在A的狀態發生改變時會自動通知B,上下兩幅圖分別代表了兩個設計的方法。

            上圖是一種較容易想到的解決方法,但是可以看出A依賴于B,兩者是緊耦合關系。
            OO中有一個重要的原則就是“依賴倒置原則”,于是就有了下圖:
            接口IA依賴于接口IB,而IA和IB是從A,B中抽象出來的相對穩定的部分,IA和IB之間的依賴關系相對穩定,不易變化。

            Ok,就是這么簡單!Observer模式的思想就是這樣!問題的關鍵在于如何抽象IA和IB,下面是GoF23對Observer模式描述的UML圖

            其中Subject即接口IA,Observer即接口IB。
            Observer只有一個方法Update,用于更新具體的Observer。
            Subject一般有一個List用于保存Observer的信息;Attach負責添加Observer;Detach負責刪除Observer;Notify通知List中的所有Observer調用Update。


            關于內存釋放:
            需要注意的是在ISubject的析構函數中清空List之前,必須首先釋放其中每個指針的內存

             自己測試用的代碼,僅供參考
              1//////////////////////////////////////////////////////////////////////////
              2//ObserverTest For Observer Pattern
              3//
              4//////////////////////////////////////////////////////////////////////////
              5
              6#include "stdafx.h"
              7#include "iostream"
              8#include <string>
              9#include <list>
             10using namespace  std;
             11
             12//賬戶參數
             13struct  AccountArgs
             14{
             15    string email;
             16    string phoneNum;
             17}
            ;
             18
             19//IObserver接口
             20class IObserver
             21{
             22public:
             23    virtual void Update(AccountArgs args) = 0;
             24}
            ;
             25
             26//具體類實現IObserver接口——Email
             27class Emailer : public IObserver
             28{
             29public:
             30    void Update(AccountArgs args)
             31    {
             32        string toAddress = args.email;
             33        cout<<"Email 通知:"<<args.email<<endl;
             34    }

             35}
            ;
             36
             37//具體類實現IObserver接口——Phone
             38class Mobile : public IObserver
             39{
             40public:
             41    void Update(AccountArgs args)
             42    {
             43        string phoneNumber = args.phoneNum;
             44        cout<<"手機 通知:"<<args.phoneNum<<endl;
             45    }

             46}
            ;
             47
             48//ISubject接口,抽象類
             49class ISubject
             50{
             51protected:
             52    //"一對多關系",可能有多個觀察者
             53    list<IObserver*> observerList;
             54protected:
             55    //notify,addObserver,removeObserver為穩定的方法,提取出來
             56    virtual void notify(AccountArgs args) = 0;
             57
             58    void addObserver(IObserver* observer)
             59    {
             60        observerList.push_back(observer);
             61    }

             62
             63    bool removeObserver(IObserver* observer)
             64    {
             65        list<IObserver*>::iterator itr;
             66        for (itr = observerList.begin();itr!=observerList.end();itr++)
             67        {
             68            if (*itr == observer)
             69            {
             70                delete *itr;
             71                observerList.erase(itr);
             72                return true;
             73            }

             74        }

             75        return false;
             76    }

             77
             78    //析構函數
             79    ~ISubject()
             80    {
             81        //首先釋放指針,之后清空List
             82        list<IObserver*>::iterator itr;
             83        for (itr = observerList.begin();itr!=observerList.end();itr++)
             84        {
             85            if ((*itr)!=NULL) { delete (*itr); }
             86        }

             87        observerList.clear();
             88    }

             89}
            ;
             90
             91//賬戶類,實現ISubject接口功能
             92class BankAccount: public ISubject
             93{
             94public:
             95    BankAccount()
             96    {
             97        addObserver(new Emailer());
             98        addObserver(new Mobile());
             99    }

            100
            101    void notify(AccountArgs args)
            102    {
            103        for(list<IObserver*>::iterator itr = observerList.begin();itr!=observerList.end();itr++)
            104        {
            105            (*itr)->Update(args);
            106        }

            107    }

            108
            109    //提款方法——通知Observer
            110    void withDraw()
            111    {
            112        //////////////////////////////////////////////////////////////////////////
            113        //提款操作.
            114        //////////////////////////////////////////////////////////////////////////
            115
            116        //Observer的一些參數
            117        AccountArgs args;
            118        args.email = "qudeqing@126.com";
            119        args.phoneNum = "1395517XXXX";
            120        notify(args);            
            121    }

            122
            123}
            ;
            124
            125int _tmain(int argc, _TCHAR* argv[])
            126{
            127    BankAccount bankAccount;
            128    bankAccount.withDraw();
            129    return 0;
            130}

            posted on 2009-04-05 22:51 Alex@VCC 閱讀(1748) 評論(3)  編輯 收藏 引用 所屬分類: 設計模式

            評論

            # re: 設計模式之Observer模式 2009-04-06 10:13 星綻紫輝

            非常感謝!設計模式其實非常重要,希望斑竹出更多更好的設計模式的文章。  回復  更多評論   

            # re: 設計模式之Observer模式 2009-05-08 12:33 brightcoder

            牛人太多了.....  回復  更多評論   

            # re: 設計模式之Observer模式 2010-04-30 10:35 calix

            樓主這么寫 不合邏輯吧?
            BankAcount 不保存用戶信息?


            class BankAccount:public Isubject{
            public:
            void notify(account &person){
            for(vector<Iobserver*>::iterator it=Observer.begin();it!=Observer.end();it++){
            (*it)->update(person);
            }
            }
            BankAccount(int num,string str){
            add(new email);
            add(new phone);
            person.email=str;
            person.phonename=num;

            }
            void withdraw(){
            // account one={1,"2"};
            notify(person);
            }
            private:
            account person;

            };  回復  更多評論   

            <2011年5月>
            24252627282930
            1234567
            891011121314
            15161718192021
            22232425262728
            2930311234

            導航

            統計

            常用鏈接

            留言簿(5)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            国产午夜精品久久久久九九| 狠狠色丁香久久婷婷综合_中| 久久久噜噜噜久久熟女AA片| 91久久婷婷国产综合精品青草| 97久久精品人人做人人爽| 久久综合一区二区无码| 亚洲国产欧美国产综合久久| 久久精品国产只有精品2020| 久久久久久av无码免费看大片| 久久精品日日躁夜夜躁欧美| 色综合久久88色综合天天| 亚洲精品NV久久久久久久久久| 国产精品一久久香蕉国产线看观看 | 狠狠狠色丁香婷婷综合久久五月| 久久国产精品一区二区| 伊人久久综合无码成人网| 久久婷婷国产麻豆91天堂| 狠狠色丁香婷婷久久综合| 国产激情久久久久影院老熟女| 午夜天堂av天堂久久久| 久久国产免费| 天天久久狠狠色综合| 日产精品久久久久久久性色| 亚洲精品无码久久久| 色8激情欧美成人久久综合电| 曰曰摸天天摸人人看久久久| 99久久精品国产高清一区二区| 国内精品伊人久久久久777| 一本大道久久东京热无码AV| 久久精品女人天堂AV麻| 日本精品久久久久中文字幕| 国产精品岛国久久久久| 国产精品久久久久影院嫩草| 国内精品久久久久久野外| av无码久久久久久不卡网站| 久久精品国产亚洲AV高清热| 久久久久久国产精品免费无码| 五月丁香综合激情六月久久 | 91精品国产高清久久久久久国产嫩草 | 精品久久久久久久国产潘金莲 | 久久精品无码一区二区三区免费|