实现一个简单的观察者模式

 

// 先看下观察者如何实现 Observer.h
# ifndef OBSEVER_H_1
# define OBSEVER_H_1
class Observer
{
public:
    Observer() { ; }
    virtual ~Observer() { ; }

    // 子类必须实现自己的Update方法
    virtual void Update(void* pArg) = 0; // 这是纯虚函数,没有函数体;
    // “=0”并不表示函数返回值为0,它只起形式上的作用,告诉编译系统“这是纯虚函数”; 
    // 纯虚函数只有函数的名字而不具备函数的功能,不能被调用。它只是通知编译系统: “在这里声明一个虚函数,留待派生类中定义”。
    // 在派生类中对此函数提供定义后,它才能具备函数的功能,可被调用。
    // 这里的 virtual 起到了接口作用
};
# endif

// Observerable.h
#pragma once

class Observer;

#include <string>
#include <list>
using namespace std;
class Observerable
{
public:
    Observerable();
    virtual ~Observerable();

    // 添加一个观察者
    void Attach(Observer* pOb);
    // 删除指定的观察者
    void Detach(Observer* pOb);

    // 获取观察者数量
    int GetObseverCount() const
    {
        return _Obs.size();
    }

    // 删除所有的观察者
    void DetachAll()
    {
        _Obs.clear();
    }

    virtual void GetSomeNews(string str)
    {
        SetChange(str);
    }
protected:
    void  SetChange(string news);

private:
    void Notify(void* pArg);

private:
    bool _bChange;
    list<Observer*> _Obs;   // 观察者使用一个标准库的List保存
};

// -------end-------end-------end-------end-------end-------end-------end-------end
// 来看一下实现
#include "stdafx.h"
#include "Observerable.h"

Observerable::Observerable():_bChange(false) // 构造函数,设置默认值(据说这种写法更高效)
{

}

Observerable::~Observerable()
{
    // 析构函数,do nothing.
}

// 添加一个观察者(指针类型),如果已经存在,直接返回
void Observerable::Attach(Observer* pOb)
{
    if (pOb == NULL)
    {
        return;
    }

    // 
    auto it = _Obs.begin();
    for (; it != _Obs.end(); it++)
    {
        if (*it == pOb)
        {
            return;
        }
    }

    _Obs.push_back(pOb);    // 在尾部插入,
}

// 删除一个观察者对象。
void Observerable::Detach(Observer* pOb)
{
    if ((pOb == NULL) || (_Obs.empty() == true))
    {
        return;
    }

    _Obs.remove(pOb);   // 这里的时间复杂度是O(n), 但观察者一般都不多,不需要用更加高级的数据结构
}

void Observerable::SetChange(string news)
{
    _bChange = true;

    Notify( ( (void*)news.c_str() ));
}

// 通知观察者
void Observerable::Notify(void* pArg)
{
    if (_bChange == false)
    {
        return;
    }

    // 遍历List,每一个观察者对象都调用 Update通知,把通知的信息pArg传递给观察者
    auto it = _Obs.begin(); // 这里使用了auto,有编译器自己推导出遍历类型
    for (; it != _Obs.end(); it++)
    {
        (*it)->Update(pArg);
    }

    _bChange = false;
}

// 来看下观察者模式要怎么用
class News : public Observerable    // 继承Observerable, 即News也是一个可观察的对象
{
public:
    virtual void GetSomeNews(string str)    // 子类实现GetSomeNews
    {
        SetChange("News: " + str);
    }
};

// 定义User1 为观察者,需要实现 Update 方法
class User1:public Observer
{
public:
    virtual void Update(void* pArg) // 子类里的virtual表示要覆盖基类的Update这个虚函数
    {
        cout << "User1 Got News: " << reinterpret_cast<char*>(pArg) <<endl;
    }
};

// 定义其他类型的观察者
class User2 :public Observer
{
public:
    virtual void Update(void* pArg)
    {
        cout << "User2 Got News: " << reinterpret_cast<char*>(pArg) <<endl;
    }
};

int main()  
{
    User1 u1;
    User2 u2;

    News n1;
    n1.GetSomeNews("T0");
    cout << n1.GetObseverCount() << endl;  // 0

    n1.Attach(&u1);
    n1.Attach(&u2);
    n1.GetSomeNews("T1");
    cout << n1.GetObseverCount() << endl;  // 2

    n1.Detach(&u2);
    n1.GetSomeNews("T2");
    cout << n1.GetObseverCount() << endl;  // 1

    n1.DetachAll();
    n1.GetSomeNews("T3");
    cout << n1.GetObseverCount() << endl;  // 0

    return 0;
}

Leave a Comment

Your email address will not be published. Required fields are marked *

PHP 8.1.1 - 16.193 ms, 0 Q