zoukankan      html  css  js  c++  java
  • 观察者模式

    观察者模式

    在GOF的《设计模式:可复用面向对象软件的基础》一书中对观察者模式是这样说的:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。当一个对象发生了变化,关注它的对象就会得到通知;这种交互也称为发布-订阅(publish-subscribe)。目标是通知的发布者,它发出通知时并不需要知道谁是它的观察者。

    再说说上面的数据和图之间的关系;不管是折线图、饼状图,还是柱状图,它们都依赖于数据;当数据发生变化时,数据对象会通知依赖于它的对象去更新;所以就有了Excel中,当数据发生变化时,对应的统计图也会自动的重绘。

    UML类图

    果冻想 | 一个原创文章分享网站

    Subject(目标)
    ——目标知道它的观察者。可以有任意多个观察者观察同一个目标;
    ——提供注册和删除观察者对象的接口。

    Observer(观察者)
    ——为那些在目标发生改变时需获得通知的对象定义一个更新接口。

    ConcreteSubject(具体目标)
    ——将有关状态存入各ConcreteObserver对象;
    ——当它的状态发生改变时,向它的各个观察者发出通知。

    ConcreteObserver(具体观察者)
    ——维护一个指向ConcreteSubject对象的引用;
    ——存储有关状态,这些状态应与目标的状态保持一致;
    ——实现Observer的更新接口以使自身状态与目标的状态保持一致。

    观察者模式按照以下方式进行协作:

    1. 当ConcreteSubject发生任何可能导致其观察者与其本身状态不一致的改变时,它将通知它的各个观察者;
    2. 在得到一个具体目标的改变通知后,ConcreteObserver对象可向目标对象查询信息。ConcreteObserver使用这些信息以使它的状态与目标对象的状态一致。

    以下是调用时序图:

    果冻想 | 一个原创文章分享网站

    使用场合

    在以下任一情况下都可以使用观察者模式:

      1. 当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立的改变和复用;
      2. 当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变;
      3. 当一个对象必须通知其它对象,而它又不能假定其它对象是谁;也就是说,你不希望这些对象是紧密耦合的。
      4. #include <iostream>
        #include <list>
        using namespace std;
        
        class Observer
        {
        public:
            virtual void Update(int) = 0;
        };
        
        class Subject
        {
        public:
            virtual void Attach(Observer *) = 0;
            virtual void Detach(Observer *) = 0;
            virtual void Notify() = 0;
        };
        
        class ConcreteObserver :public Observer
        {
        public:
            ConcreteObserver(Subject *pSubject) :m_pSubject(pSubject){}
            void Update(int value)
            {
                cout << "ConcreteObserver get the update,New State:" << value << endl;
            }
        private:
            Subject *m_pSubject;
        };
        
        class ConcreteObserver2:public Observer
        {
        public:
            ConcreteObserver2(Subject *pSubject) :m_pSubject(pSubject){}
            void Update(int value)
            {
                cout << "ConcreteObserver2 get the update.New State:" << value << endl;
            }
        private:
            Subject *m_pSubject;
        };
        
        class ConcreteSubject :public Subject
        {
        public:
            void Attach(Observer *pObserver);
            void Detach(Observer *pObserver);
            void Notify();
            void SetState(int state)
            {
                m_iState = state;
            }
        private:
            std::list<Observer *> m_ObserverList;
            int m_iState;
        };
        
        void ConcreteSubject::Attach(Observer *pObserver)
        {
            m_ObserverList.push_back(pObserver);
        }
        
        void ConcreteSubject::Detach(Observer *pObserver)
        {
            m_ObserverList.remove(pObserver);
        }
        
        void ConcreteSubject::Notify()
        {
            std::list<Observer *>::iterator it = m_ObserverList.begin();
            while (it!=m_ObserverList.end())
            {
                (*it)->Update(m_iState);
                ++it;
            }
        }
        
        int main()
        {
            //Create Subject
            ConcreteSubject *pSubject = new ConcreteSubject();
            //Create Observer
            Observer *pObserver = new ConcreteObserver(pSubject);
            Observer *pObserver2 = new ConcreteObserver2(pSubject);
            //change the state
            pSubject->SetState(2);
            //Register the observer
            pSubject->Attach(pObserver); pSubject->Attach(pObserver2);
            pSubject->Notify();
            pSubject->Detach(pObserver);
            pSubject->SetState(3);
            pSubject->Notify();
        
            delete pObserver;
            delete pObserver2;
            delete pSubject;
        }

     观察者模式概念:定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。“Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.” – GoF

    UML图

    特点:

        1.观察者模式定义了对象之间一对多的关系。

        2.主题(也就是可观察者)用一个共同的接口来更新观察者。

        3.观察者和可观察者用松耦合的方式结合,可观察者不知道观察者的细节,只知道观察者实现了观察者接口

        4.有多个观察者时,不可以依赖特点的通知次序。

    #include <iostream>
    using namespace std;
    #include <vector>
    
    class Observer;
    //被观察者接口
    class Account
    {
    protected:
        vector<Observer*> observers;
        double balance;
    public:
        virtual void add_observers(Observer*) = 0;
        virtual void remove_observers(Observer*) = 0;
        virtual void notify_observers() = 0;
        virtual void set_balance(double balance) = 0;
        virtual double get_balance() = 0;
    public:
        virtual ~Account()
        {
            cout << "in the destructor of Account" << endl;
        }
    };
    
    //Observer 抽象类接口
    class Observer
    {
    protected:
        Account* account;  //也可以在子类中绑定观察的对象
    public:
        Observer(Account* _account) :account(_account){}
        virtual void handle_event() = 0;
        virtual void set_account_balance(double balance) = 0;
        virtual ~Observer()
        {
            cout << "in the destructor of Account" << endl;
        }
    };
    
    //BankAccount具体类
    class BankAccount :public Account
    {
    public:
        ~BankAccount(){ cout << "in the destructor of bankAccount"; }
    public:
        void add_observers(Observer* o)
        {
            observers.push_back(o);
        }
        void remove_observers(Observer* o)
        {
            for (auto it = observers.begin(); it != observers.end(); it++)
            {
                if (*it == o)
                {
                    observers.erase(it);
                    return;
                }
            }
        }
        void notify_observers()
        {
            for (vector<Observer*>::const_iterator it = observers.begin(); it != observers.end(); it++)
            {
                (*it)->handle_event();
            }
        }
        void set_balance(double balance)
        {
            this->balance = balance;
            notify_observers();
        }
        double get_balance()
        {
            return balance;
        }
    };
    
    
    class ATM :public Observer
    {
    public:
        ATM(Account* _account) :Observer(_account){}
        ~ATM()
        {
            cout << "int the destructor of ATM" << endl;
        }
    public:
        void handle_event()
        {
            cout << "ATM:the balance of bank accont is changed to" << account->get_balance() << endl;
        }
        void set_account_balance(double balance)
        {
            account->set_balance(balance);
        }
    };
    
    class InternetBankService :public Observer
    {
    public:
        InternetBankService(Account* _account) :Observer(_account){}
        ~InternetBankService()
        {
            cout << "in the destructor InternetBankService" << endl;
        }
    public:
        void handle_event()
        {
            cout << "IBS:the balance of bank account is changed to" << account->get_balance() << endl;
        }
        void set_account_balance(double balance)
        {
            account->set_balance(balance);
        }
    };
    
    int main()
    { 
        Account* account = new BankAccount();   //申明具体的被观察者
        Observer* atm_observer = new ATM(account);  //申明具体的观察者
        Observer* ibs_observer = new InternetBankService(account);
        account->add_observers(atm_observer);   //一对多的关系,很多观察者观察一个东西
        account->add_observers(ibs_observer);
    
        account->set_balance(1000.12);  //被观察者变化,引起所有观察者变化
    
        cout << "Event is triggered by atm_observer" << endl;
        cout << "==============" << endl;
        atm_observer->set_account_balance(1000.34);   //某一个观察者引起被观察者变化,也会是其他的观察者变化
    
        cout << "Event is triggered by ibs_observer" << endl;
        cout << "==============" << endl;
        ibs_observer->set_account_balance(1000.78);
    
        delete atm_observer;
        delete ibs_observer;
        return 0;
    }
  • 相关阅读:
    利用jmSlip写一个移动端顶部日历选择组件
    JS写的排序算法演示
    jmSlip WEB前端滑屏组件
    如何:使用 Visual Basic 编写基于 Unity3D 的计算器
    验证 .NET 4.6 的 SIMD 硬件加速支持的重要性
    VB 2015 的 闭包(Closure)
    VS "15" 预览 5 中 VB 15 新增的功能
    演练:使用Xamarin.Forms开发产品介绍性质的应用(VB版)
    UWP游戏防内存修改器的方法
    优化win2d实现的萤火虫粒子效果
  • 原文地址:https://www.cnblogs.com/ranjiewen/p/5610481.html
Copyright © 2011-2022 走看看