设计模式 - Observer观察者模式

本文介绍了一种常用的设计模式——观察者模式,详细解释了Subject与Observers之间的交互原理,并通过具体的代码示例展示了如何实现观察者模式。此外还讨论了多线程环境下数据同步的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 简单描述

观察者模式主要包括:Subject与Observers。通常observer会有多个而subject只有一个。observer将自己注册到subject中,当subject中的信息发生变化时subject便会通知该observer进行更新。subject保存所有注册的observer实例信息,在信息发生变化时通知其保存的每一个observer。这种方式是回调的一种应用。observer保存着subject的指针,subject使用array或其它同期保存observer。
subject通知observer时可以使用“推”或“拉”的方式,“推”就是subject在通知observer信息变化时直接将变化的信息作为参数传递给observer,“拉”就是subject仅仅通知observer信息有变化,而由observer自己去取得变化的信息。在多线程环境下,“推”的方式更能保证数据的准确性。

2.实例程序

subject中保存注册的observer的指针,为了使每个observer只在subject中保存一份(信息发生变化时每个observer只通知一次)使用std::set保存指针信息。

2.1 定义信息提供者

信息提供者(subject)包含observer集合成员,用来储存所有注册的观察者。attach(Observer*)用来将新的observer放入集合中。notify()接口实现当有数据变化时,遍历observer集合并通知所有注册的observer。
注意:例子中将observer的raw指针放入Observer集合,但实际使用中应该使用弱指针来避免内存泄露以及野指针问题。

//subject.h

#include <set>

class Observer;
class Subject
{
public:
    Subject(){}

    ~Subject(){}

    // regist a new observer if it does not in m_observer;
    void attach(Observer* observer);

    // remove one observer in m_observer;
    void detach(Observer* observer);

    // notify the observers to update messages;
    void notify();

private:
    std::set<Observer*> m_observer;
    typedef std::set<Observer*>::iterator ObserverIter;
};


//subject.cpp
#include <iostream>
#include "Subject.h"
#include "Observer.h"
using namespace std;

void Subject::attach(Observer* observer)
{
    if (NULL != observer)
    {
        pair<ObserverIter, bool> result = m_observer.insert(observer);
        if (true == result.second)
        {
            cout<<"Subject::attach successfully registed"<<endl;
        }
        else
        {
            cout<<"Subject::attach already registed"<<endl;
        }
    }
}


void Subject::detach(Observer* observer)
{
    if (NULL != observer)
    {
        int num = m_observer.erase(observer);
        if (0 < num)
        {
            cout<<"Subject::detach successfully removed"<<endl;
        }
        else
        {
            cout<<"Subject::detach do not need remove"<<endl;
        }
    }
}


void Subject::notify()
{
    for (ObserverIter i = m_observer.begin(); i != m_observer.end(); ++i)
    {
        (*i)->update(8);
    }
}


2.2 定义观察者

观察者在构造时接收一个subject的指针,用来将自己注册到相应的subject中去。观察者实现了一个uodate()接口用来处理“观察到的”新数据。

// observer.h

class Subject;
class Observer
{
public:
    // regist to subject when construct
    Observer(Subject* subject): m_subject(subject){}

    virtual ~Observer(){}

    // update message
    virtual void update(int updateStr) = 0;

    // remove from the old subject and regist to a new subject;
    void regist(Subject* subject);

    // remove from the old subject;
    void remove();

protected:
    Subject* m_subject;
};

class ObserverA: public Observer
{
public:
    ObserverA(Subject* subject);
    virtual ~ObserverA(){}
    virtual void update(int updateStr);

};

class ObserverB: public Observer
{
public:
    ObserverB(Subject* subject);
    virtual ~ObserverB(){}
    virtual void update(int updateStr);

};

// observer.cpp

#include <iostream>
#include "Observer.h"
#include "Subject.h"
using namespace std;

void Observer::regist(Subject* subject)
{
    if (NULL == subject)
    {
        cout<<"Observer::regist subject is NULL"<<endl;
        return;
    }
    if (m_subject != subject)
    {
        remove();
        m_subject = subject;
        m_subject->attach(this);
    }
    else
    {
        cout<<"Observer::regist no need attach operation"<<endl;
    }
}

void Observer::remove()
{
    if (NULL != m_subject)
    {
        m_subject->detach(this);
        m_subject = NULL;
    }
}

ObserverA::ObserverA(Subject* subject): Observer(subject)
{
    if (NULL != m_subject)
    {
        m_subject->attach(this);
    }
}

void ObserverA::update(int updateStr)
{
    cout<<"ObserverA::update:   "<<updateStr<<endl;
}

ObserverB::ObserverB(Subject* subject): Observer(subject)
{
    if (NULL != m_subject)
    {
        m_subject->attach(this);
    }
}

void ObserverB::update(int updateStr)
{
    cout<<"ObserverB::update:   "<<updateStr<<endl;
}


2.3 测试程序

// test.cpp

#include <iostream>
#include "Subject.h"
#include "Observer.h"
using namespace std;

int main(int argc, char const *argv[])
{
    /* code */
    Subject* pSubject = new Subject();
    ObserverA obA(pSubject);
    ObserverB obB(pSubject);
    pSubject->notify();
    obB.remove();
    pSubject->notify();
    obB.regist(pSubject);
    obB.regist(pSubject);
    pSubject->notify();
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值