zoukankan      html  css  js  c++  java
  • 设计模式学习系列3 观察者模式

    观察者模式,又称为发布订阅模式,收听模式等,该模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新,下面的代码主要参考《大话设计模式》这本书,我用C++写了一边,并且做了一些修改和优化。

    故事背景:无

    故事的逻辑:观察者的状态修改的时候 ,通知依附于它本身的被通知者,通知者收到状态修改的信息之后作出状态修改的信息输出

      
    /*设计模式学习系列之观察者模式
    * 参考书籍《大话设计模式》 
    * 观察者莫模式的主要用途:当一个对象的改变需要同时改变其他对象状态的时候,该模式 
    * 可以将二者解除耦合,使二者独立的进行改变和复用 
    * 
    * 例子的架构:通知者与被通知者,通知者保留被统治者的列表,被通知者得到通知后 更改自己的状态 
    */ 
    #include <iostream>
    using namespace std ;
    #include <vector>
    
    //被通知者抽象类 
    class Subject 
    {
    private:
        unsigned int m_id ;
    public:
        Subject():m_id(0){}
         
        virtual ~Subject(){}    
        
        void SetId(const unsigned int& id){m_id = id ;}
        unsigned int  GetId(){return m_id;}  
        
        //更新状态 ,虚函数,需要使用子类自己实现 
        virtual void  UpdateState(){ cout << "base class
    " << endl; }
    };
    
    //通知者抽象类 
    class Observe
    {
    private:
        vector<Subject*> m_SubjectList;
    public:
    
        Observe(){}
        virtual ~Observe(){}
        
        //增加被通知者
        void  Attach( Subject* sub )
        {
            m_SubjectList.push_back(sub);                    
        }
        
        //删除被通知者 
        void  Detach( Subject* sub)
        {
            vector<Subject*>::iterator it = m_SubjectList.begin();
            for( ; it != m_SubjectList.end() ; ++it)
            {
                if( (*it)->GetId() == sub->GetId())
                {
                    m_SubjectList.erase(it);
                }
            }
        }
        
        //通知所有对象 
        void Update()
        {
            vector<Subject*>::iterator it = m_SubjectList.begin();
            for( ; it != m_SubjectList.end() ; ++it)
            {
                (*it)->UpdateState();
            }
        } 
    };
    
    //观察者 实现类 
    class Observe1:public Observe
    {
    public:
        void SetState(const string & str)
        {
            m_State = str ;
        }
        
        string GetState()
        {
            return m_State;    
        }
    private:
        string m_State ;
    } ;
    
    //被通知者1 
    class Subject1:public Subject
    {
    private:
        string m_strState ;
        Observe m_Observe ;
    public:
        Subject1(const Observe1 &obs ,const int& id)
        {    
            m_Observe  = obs ;
            SetId(id);
        }
        
        ~Subject1(){}
    
    
        void UpdateState()
        {
            cout << "Subject1 收到通知,通知内容:" << endl ;    
        }    
    } ;
    
    //被通知者2
    class Subject2:public Subject
    {
    private:
        string m_strState ;
        Observe m_Observe ;
    public:
        Subject2(const Observe1 &obs ,const int& id)
        {    
            m_Observe  = obs ;
            SetId(id);
        }
        
        ~Subject2(){}
    
        void UpdateState()
        {
            cout << "Subject2 收到通知,通知内容:" << endl ;    
        }    
    };
    
    //==============================================================
    int main()
    {
        Observe1 obs ;
    
        Subject1 *pSub1 = new Subject1(obs,1);
        Subject2 *pSub2 = new Subject2(obs,2);    
        obs.Attach(pSub1);
        obs.Attach(pSub2);    
        
        obs.SetState("xxxxxx");
        
        obs.Update();
            
        return 0 ;
    }
    

    记录一下实现过程中遇到的问题:

    (1)被通知者列表为指针类型,这样才会使用虚函数的特性,观察者进行通知的时候会通知被观察者的子类而不是基类

    (2)基类的析构函数为虚函数,析构函数执行时先调用派生类的析构函数,其次才调用基类的析构函数。如果析构函数不是虚函数,而程序执行时又要通过基类的指针去销毁派生类的动态对象,那么用delete销毁对象时,只调用了基类的析构函数,未调用派生类的析构函数。这样会造成销毁对象不完全。

    (3)上述方法中 被通知者不一定要记录观察者的信息,只要作出自己的修改

    细雨淅淅 标签:
  • 相关阅读:
    retain assign copy (unsigned long)
    myeclipse未设置断点,但不断跳出debug
    SOAP tomcat7.0 HelloWorld
    JAVA第二天数据类型和循环
    java中产生随机数的几种方法
    java的第一个程序 Hello World
    java中产生随机数的几种方法
    用加减来简单的看策略类
    用加减来简单的看策略类
    奇数阶幻方
  • 原文地址:https://www.cnblogs.com/zsb517/p/3409356.html
Copyright © 2011-2022 走看看