观察者模式,或者称作发布/订阅模式(Pubish/Subcribe)。其中关键点在于,被观察者(发布者)的实现中持有一个集合,对集合执行添加/删除操作就是增加/减少观察(订阅)者数目,是一对多的关系,侧重“监听",当一方发生情况时多方可以获得该情况。同时,被观察者也定义了一个通知方法来通知观察者们。这个模式常用于事件循环中。

注:本文基于C++,使用boost库中的指针容器和智能指针来实现集合,但是在编译时发现各种错误,经查阅资料后得知对于观察者模式是典型的不适用于智能指针的例子。因为观察者和被观察者不是彼此拥有的,特别是当一个对象具有指向另一个对象的指针时它注册为观察者,从逻辑上而言双方耦合性并不强,被观察者被破坏时会发布通知给观察者们,与智能指针并不匹配。我觉得这个例子值得多次思考,因此写下这篇文章。

头文件

类型定义

// types.h
#ifndef TYPES_H
#define TYPES_H

#include <boost/ptr_container/ptr_container.hpp>
#include "Observer.h"
#include "Observerable.h"

class Observer;
class Observerale;

typedef boost::shared_ptr<Observer> pObserver;
typedef boost::shared_ptr<Observerable> pObserverable;

#endif

观察者

// observer.h  观察者/订阅者
#ifndef OBSERVER_H
#define OBSERVER_H

#include "types.h"

class Observerable;
class Observer
{
public:
    virtual ~Observer() { }
    virtual void upDate() = 0;
    void observe(pObserverable s);  //订阅
private:
    pObserver subjects_;  //订阅对象
};

#endif 

被观察者

//Observerable.h
#ifndef OBSERVERABLE_H
#define OBSERVERABLE_H

#include <iostream>
#include <string>
#include <memory>
#include <algorithm>
#include <list>
#include <boost/ptr_container/ptr_container.hpp>
#include "types.h"

class Observer;
class Observerable 
{
public:
    explicit Observerable();
    virtual ~Observerable() { }

    void Register(pObserver s) { observers_.push_back(s) }
    void Unregister(pObserver s) { observers_.remove(s) }
    void notify();

    virtual void setStatus(const string& s) { status_ = s; }
    virtual std::string getStatus() { return status_; }

private:
    boost::ptr_list<Observer> observers_;
protected:
    std::string status_;

CPP文件

观察者

//Observer.cpp
#include "Observer.h"
void Observer::observer(pObserverable s) 
{
    s->Register(this);
    subjects_ = s;
}

被观察者

//Observerable.cpp
#include "Observer.h"
#include "Observerable.h"


void Observerable::notify() {
    boost::ptr_list<Observer>::iterator it = observers_.begin();
    for(;it != observers_.end(); ++it) {
        (*it)->upDate();
    }
}

void Observerable::Unregister(pObserver x)
{
    boost::ptr_list<Observer>::iterator it = observers_.begin();
    for(;it != observers_.end();) {
        if(it == x) {
            boost::ptr_list<Observer>::auto_type p = Observers_.release(it);
            break;
        }
        it++;
    }
}

main函数

#include "Observer.h"
#include "Observerable.h"

//看博客的人,订阅者
class BolgObserver : public Observer
{
public:
    BlogObserver(const std::string& name) : name_(name) { }
private:
    std::string name_; 
};

//发布博客的人,被观察/发布者
class BlogHexo : public Observerable
{
public:
    BlogHexo(const string& name) : name_(name) { }
    ~BlogHexo() { }
private:
    std::string name_;
};

void BlogHexo::setStatus(const string& s)
{
    status_ = name_ + "'s Blog status is" + s;
    std::cout << status_ << std::endl;
}

string BlogHexo::getStatus()
{
    return status_;
}

void BolgObserver::upDate()
{
    string status = subjects_->getStatus();
    std::cout << status << std::endl;
    std::cout << name_ << " is notified" << std::endl;
}

int main()
{
    //订阅者p和q,发布者blogHost
    pObserver p(new Observer(sb1));
    pObserver q(new Observer(sb2));
    pObserverable blogHost(new Observerable("yangwq"));

    //blogHost更新状态,订阅者们订阅blogHost
    //blogHost通知订阅者
    blogHost->setStatus("Update blog design pattern");
    p->observer(blogHost);
    q->observer(blogHost);
    blogHost->notify();
    return 0;
}