• <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 閱讀(1747) 評論(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;

            };  回復  更多評論   

            <2009年4月>
            2930311234
            567891011
            12131415161718
            19202122232425
            262728293012
            3456789

            導航

            統計

            常用鏈接

            留言簿(5)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            亚洲人成电影网站久久| 久久精品国产精品青草| 久久人人爽人人人人爽AV| 久久久久亚洲av成人网人人软件| 亚洲精品无码久久不卡| 久久无码人妻一区二区三区| AA级片免费看视频久久| 国产精品久久久久蜜芽| 青青草国产精品久久久久| 欧美伊人久久大香线蕉综合69| 天天躁日日躁狠狠久久 | 99久久精品无码一区二区毛片 | 一本一本久久A久久综合精品 | 亚洲国产精品狼友中文久久久| 无码人妻久久一区二区三区免费 | 久久久精品国产亚洲成人满18免费网站| 久久亚洲AV无码精品色午夜| 久久99亚洲综合精品首页| 囯产精品久久久久久久久蜜桃| 久久久国产精品福利免费| 久久影院综合精品| 国内精品久久国产| 久久影视综合亚洲| av国内精品久久久久影院| 久久久久高潮综合影院| 久久久精品无码专区不卡| 久久久久久狠狠丁香| 色欲综合久久躁天天躁蜜桃| 色播久久人人爽人人爽人人片aV| 久久久久久久综合日本亚洲| 亚洲精品高清国产一线久久| 久久这里都是精品| 区久久AAA片69亚洲| 欧美激情精品久久久久久久| 精品久久久久久无码人妻热| 久久综合九色综合97_久久久| 伊人久久大香线蕉亚洲| 亚洲伊人久久成综合人影院 | 91精品国产综合久久精品| 日韩精品久久久久久免费| 无码日韩人妻精品久久蜜桃 |