Published on

设计模式(19)——观察者 Observer

Authors
  • avatar
    Name
    Leon
    Twitter

十九、Observer(观察者模式,别名 Dependents 依赖,Publish-Subjects 发布-订阅)

1. 意图:

  定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖的对象都得到通知并被自动更新。

2. 适用:

  1. 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这二者封装在独立的对象中以使它们可以各自独立地使用和复用。
  2. 当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。
  3. 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的。

3. 类图:

4. 应用:

  观察者模式用好莱坞法则来解释再好不过了——“不要给我们打电话,我们会打电话给你(don't call us, we'll call you)”。网络编程中有两种模式,同步模式和异步模式。异步模式的思想就是观察者模式的核心。异步模式怎么工作的呢?比如某个 socket 现在要收包,就调用 select,告诉系统要收包,然后 socket 就不会傻等着阻塞在收包的地方,而是直接返回腾出 cpu 让程序去做其他事情。等系统收到包后,就会唤醒 socket 来收包。同步模式是怎么做的?同样是 socket 要收包,它就是占着 cpu 傻等在那里,程序不能做其它事情了,直到收到包才继续执行执行下去。   消息后台 Msgcenter 连接了多个模块,比如最近联系人,漫游服务器,Conn, OnlinePush, MsgDb。这些模块针对不同消息(类型,号码,收发终端,终端版本,消息内容)可能会做一些特殊逻辑。这种情况下可以将多个模块抽象成多个观察者 Observer,去监听特定的消息并做特殊处理。在这里不同的消息类型就是事件。   MVC 结构就是 Observer 的一个实例,MVC 实现了业务逻辑和表示层的解耦。   Java 语言本身提供了 Observer 模式的实现接口。

5. 中间层思考:

  初看观察者模式并没有使用中间层,但其实观察者 Observer 就是引入的中间层。如果没有 Observer 这样一个抽象层,事件的产生者 Subject 需要知道具体事件监听者的具体类型,才能通知到每一个监听者。通过引入 Observer 这样一个抽象层,事件的生产者 Subject 可以不用关心通知的是哪些模块,只需要统一地调用 Notify 函数,其它事情通过调用统一的for循环去处理了。

6. C++实现:

  1. 编写目标类 Subject,含有一个 list 作为存储它的观察者 Observer 对象的容器,编写添加和减少观察者的函数 Attach(Observer*)Detach(Observer*),编写一个通知函数 Notify() 用于更新它的观察者们
  2. 编写观察者类 Observerhas-a Subject 对象 _sub,通过具体类的构造函数初始化 Subject 如 ConcreteObserverA(Sujbect* sub),含一个更新操作 Update(Subject* sub)

Observer.h

//Observer.h
#pragma once

#include "Subject.h"
#include <string>
using namespace::std;
typedef string State;

class Observer {
public:
	virtual ~Observer();
	virtual void Update(Subject* sub) = 0;
	virtual void PrintInfo() = 0;
protected:
	Observer();
	State _st;
private:
};

class ConcreteObserverA : public Observer {
public:
	virtual Subject* GetSubject();
	ConcreteObserverA(Subject* sub);
	virtual ~ConcreteObserverA();
	void Update(Subject* sub);
	void PrintInfo();
protected:
private:
	Subject* _sub;
};

class ConcreteObserverB : public Observer {
public:
	virtual Subject* GetSubject();
	ConcreteObserverB(Subject* sub);
	virtual ~ConcreteObserverB();
	void Update(Subject* sub);
	void PrintInfo();
protected:
private:
	Subject* _sub;
};

Observer.cpp

//Observer.cpp

#include "Observer.h"
#include "Subject.h"

#include <iostream>
#include <string>

using namespace::std;

Observer::Observer() {
	_st = '\0';
}
Observer::~Observer() {}
ConcreteObserverA::ConcreteObserverA(Subject* sub) {
	_sub = sub;
	_sub->Attach(this);
}
ConcreteObserverA::~ConcreteObserverA() {
	_sub->Detach(this);
	if (_sub != 0)
		delete _sub;
}
Subject* ConcreteObserverA::GetSubject() {
	return _sub;
}
void ConcreteObserverA::PrintInfo() {
	cout << "ConcreteObserverA observer...." << _sub->GetState() << endl;
}
void ConcreteObserverA::Update(Subject* sub) {
	_st = sub->GetState();
	PrintInfo();
}

ConcreteObserverB::ConcreteObserverB(Subject* sub) {
	_sub = sub;
	_sub->Attach(this);
}
ConcreteObserverB::~ConcreteObserverB() {
	_sub->Detach(this);
	if (_sub != 0)
		delete _sub;
}
Subject* ConcreteObserverB::GetSubject() {
	return _sub;
}
void ConcreteObserverB::PrintInfo() {
	cout << "ConcreteObserverB observer..." << _sub->GetState() << endl;
}
void ConcreteObserverB::Update(Subject* sub) {
	_st = sub->GetState();
	PrintInfo();
}

Subject.h

//Subject.h
#pragma once

#include <list>
#include <string>

using namespace::std;

typedef string State;

class Observer;

class Subject {
public:
	virtual ~Subject();
	virtual void Attach(Observer* obv);
	virtual void Detach(Observer* obv);
	virtual void Notify();
	virtual void SetState(const State& st) = 0;
	virtual State GetState() = 0;
protected:
	Subject();
private:
	list<Observer*>* _obvs;
};

class ConcreteSubject : public Subject {
public:
	ConcreteSubject();
	~ConcreteSubject();
	State GetState();
	void SetState(const State& st);
protected:
private:
	State _st;
};

Subject.cpp

//Subject.cpp

#include "Subject.h"
#include "Observer.h"

#include <iostream>
#include <list>

using namespace::std;

typedef string State;

Subject::Subject() {
	// 在模板的使用之前一定要 new 创建
	_obvs = new list<Observer*>;
}
Subject::~Subject() {}
void Subject::Attach(Observer* obv) {
	_obvs->push_front(obv);
}
void Subject::Detach(Observer* obv) {
	if (obv != NULL) {
		_obvs->remove(obv);
	}
}
void Subject::Notify() {
	list<Observer*>::iterator it;
	it = _obvs->begin();
	for (; it != _obvs->end(); it++) {
		(*it)->Update(this);
	}
}

ConcreteSubject::ConcreteSubject() {
	_st = '\0';
}
ConcreteSubject::~ConcreteSubject() {}
State ConcreteSubject::GetState() {
	return _st;
}
void ConcreteSubject::SetState(const State& st) {
	_st = st;
}

main.cpp

//main.cpp

#include "Subject.h"
#include "Observer.h"

#include <iostream>

using namespace::std;

int main(int argc, char* argv[]) {
	ConcreteSubject* sub = new ConcreteSubject();
	Observer* o1 = new ConcreteObserverA(sub);
	Observer* o2 = new ConcreteObserverB(sub);
	sub->SetState("old");
	sub->Notify();
	sub->SetState("new");	// 也可以由 Observer 调用
	sub->Notify();
	return 0;
}