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

           观察者模式又被称为发布订阅模式。它定义了对象之间一对多的依赖,当一个对象状态发生改变时,它的所有依赖者都会收到通知并自动更新相关内容。即建立一个(Subject类)对多(Observer类)的关系,能够使得当Subject的对象变化的时候,依赖这个的多个Observe的对象实例也能够同步进行相应的改变。

    优点: 1、观察者和被观察者是抽象耦合的。 2、可以建立一套触发机制。

    缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

    2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。

    3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

     设计骨架如下:

    各个角色解释如下:

    抽象Subject角色:抽象主题角色提供维护一个观察者对象集合的操作方法,对集合的增加、删除等。

    具体ConcreteSubject角色:将有关状态存入具体的观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发通知。具体主题角色负责实现抽象基类中的方法。

    抽象Observer角色:为具体观察者提供一个更新接口。

    具体ConcreteObserver角色:存储自身的状态,实现抽象观察者提供的更新改变的接口。

       举一个老板与职员的例子,在某IT公司的上午,有几个员工在上班偷偷划水,但怕被老板发现,他们让离老板办公室最近的小A负责望风,当老板来时,通知小B,小C,小D他们做出改变。要编程来描述这个过程,这里就可以用观察者模式来实现了,把小A当做Subject,其他要通知的员工则是Observer,代码如下:

    #include <iostream>
    #include<vector>
    using namespace std;
    class Observer;
    //抽象被观察者
    class Subject
    {
    public:
        virtual void Attach(Observer *) = 0;
        virtual void Detach(Observer *) = 0;
        virtual void Notify() = 0;
        virtual string GetState()
        {
            return state_;
        }
        void SetState(string state)
        {
            state_= state;
        }
    protected:
        vector<Observer *> ob;
        string state_;
    };
    //具体被观察者
    class ConcreteSubject : public Subject
    {
    public:
        void Attach(Observer *pObserver)
        {
            ob.push_back(pObserver);
        }
        void Detach(Observer *pObserver)
        {
            vector<Observer*>::iterator t;
            for(t=ob.begin(); t!=ob.end(); t++)
                if(*t==pObserver)
                    ob.erase(t);
        }
        void Notify();
    };
    //抽象观察者
    class Observer
    {
    protected:
        Subject *subject;
    public:
        Observer(Subject *s)
        {
            subject = s;
            subject->Attach(this);
        }
        virtual void Update() = 0;
    };
    //核心操作:循环通知所有观察者
    void ConcreteSubject::Notify()
    {
        vector<Observer*>::iterator t;
        for(t=ob.begin(); t!=ob.end(); t++)
            (*t)->Update();
    }
    //具体观察者1
    class Observer1 : public Observer
    {
    public:
        Observer1(Subject *s): Observer(s)
        {
            cout<<"小B在看电影"<< endl;
        }
        virtual void Update()
        {
            cout  << subject->GetState() << ",小B开始好好工作"<< endl;
        }
    };
    //具体观察者2
    class Observer2 : public Observer
    {
    public:
        Observer2(Subject *s): Observer(s)
        {
            cout <<"小C在玩游戏"<< endl;
        }
        virtual void Update()
        {
            cout << subject->GetState() << ",小C开始好好工作"<< endl;
        }
    };
    //具体观察者2
    class Observer3 : public Observer
    {
    public:
        Observer3(Subject *s): Observer(s)
        {
            cout <<"小D在聊天"<< endl;
        }
        virtual void Update()
        {
            cout << subject->GetState() << ",小D开始好好工作"<< endl;
        }
    };
    
    int main()
    {
        // 创建被观察者
        Subject *p_subject = new ConcreteSubject();
        // 创建观察者
        Observer *p_observer1 = new Observer1(p_subject);
        Observer *p_observer2 = new Observer2(p_subject);
        Observer *p_observer3 = new Observer3(p_subject);
        // 改变状态
        cout<<"老板来了,小A通知"<<endl;
        p_subject->SetState("老板来了");
        p_subject->Notify();
        cout<<"小B不需要通知"<<endl;
        // 注销观察值小B
        p_subject->Detach(p_observer1);
        cout<<"老板又来了,小A通知"<<endl;
        p_subject->SetState("老板来了");
        p_subject->Notify();
    }

      

     

     

      
      

     

     

  • 相关阅读:
    推荐阅读20100603
    [ASP.NET4之旅]Circular file references are not allowed
    满园尽是503,记曾经的一次IIS 7性能考验
    VS2010小Bug:找不到System.Web.Extensions.dll引用
    VS2010奇异Bug:三个中文符号在CSS文件中轻松让VS2010崩溃
    推荐阅读20100528
    Windows平台网站文件同步备份解决方案——cwRsyn
    推荐阅读20100803
    在IE8中使用建行企业网银的解决方法
    博客园已经用上NorthScale Memcached Server
  • 原文地址:https://www.cnblogs.com/xiaxiaopi/p/12524516.html
Copyright © 2011-2022 走看看