- Published on
设计模式(19)——观察者 Observer
- Authors
- Name
- Leon
十九、Observer(观察者模式,别名 Dependents 依赖,Publish-Subjects 发布-订阅)
1. 意图:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖的对象都得到通知并被自动更新。
2. 适用:
- 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这二者封装在独立的对象中以使它们可以各自独立地使用和复用。
- 当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。
- 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的。
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++实现:
- 编写目标类
Subject
,含有一个 list 作为存储它的观察者Observer
对象的容器,编写添加和减少观察者的函数Attach(Observer*)
和Detach(Observer*)
,编写一个通知函数Notify()
用于更新它的观察者们 - 编写观察者类
Observer
,has-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;
}