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

来源:互联网 发布:wamp怎么运行php 编辑:程序博客网 时间:2024/06/06 14:09

目录:

设计模式学习笔记首页
设计模式(1)——抽象工厂 AbstractFactory
设计模式(2)——生成器 Builder
设计模式(3)——工厂方法 Factory Method
设计模式(4)——原型 Prototype
设计模式(5)——单例 Singleton
设计模式(6)——适配器 Adapter
设计模式(7)——桥接 Bridge
设计模式(8)——组合 Composite
设计模式(9)——装饰 Decorator
设计模式(10)——外观 Facade
设计模式(11)——享元 Flyweight
设计模式(12)——代理 Proxy
设计模式(13)——职责链 Chain Of Responsibility
设计模式(14)——命令 Command
设计模式(15)——解释器 Interpreter
设计模式(16)——迭代器 Iterator
设计模式(17)——中介者 Mediator
设计模式(18)——备忘录 Memento
设计模式(19)——观察者 Observer
设计模式(20)——状态 State
设计模式(21)——策略 Strategy
设计模式(22)——模板方法 Template Method
设计模式(23)——访问者 Visitor

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

1. 意图:

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

2. 适用:

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

3. 类图:

image

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;} 
原创粉丝点击