设计模式学习系列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)上述方法中 被通知者不一定要记录观察者的信息,只要作出自己的修改

细雨淅淅 标签:
原文地址:https://www.cnblogs.com/zsb517/p/3409356.html