转http://patmusing.blog.163.com/blog/static/13583496020101501923571/

也称为Dependents或Publish-Subscribe模式。

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

“Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.” – GoF

将一个系统分解成一系列的相互协作的类会产生一个普遍存在的副作用:需要维护相关对象之间的一致性。要维护各对象之间的一致性,通常的做法就是使这些对象之间彼此紧耦合,但是这样又会降低他们的可重用性。

比如,许多图形界面工具包将用户界面的展示和底层应用数据分开。用来定义应用数据和界面展示的类可以独立重复使用,也可以一起使用。表格对象和柱状图对象可以同时展示同一个应用数据对象中的数据,但表格对象和柱状图对象,彼此无需知道对方的存在。但实际情况中,它们却似乎又知道对方的存在,比如当一个用户改动表格中的信息,柱状图也会随之改变,反之亦然。

这种行为暗示了表格对象和柱状图对象都依赖了数据对象。如果一个用户改变了表格中的数据,这种改动会立即被反映到数据对象中,数据对象中的数据发生了这种改变,会立即通知柱状图对象,柱状图对象得到通知后,会对柱状图的显示做出相应的改变。

Observer模式描述如何建立这些关系。本模式中的关键对象是Subject和Observer。一个Subject可以有任意多独立的Observer。如果Subject的内容发生改变,所有的Observer都会得到通知,每个Observer则查询Subject,以保持与其状态同步。

这种交互也称为publish-subscribe(发布者-注册)。Subject就是publisher,任意数量的Observer可以注册以接收通知。

UML类图:

业务案例:

说明:

-          通过ATM、InternetBankingService和MobileBankingService均可改动银行账户余额;

-          银行账户余额还可以有其他方式改变,比如柜台(此例并未用及,用来模拟银行账户自身的余额变化);

-          只要一上其中之一改变了银行账户中的余额,其他相关各方均可以收到余额变动信息;

-          Bank Account是Subject,ATM、InternetBankingService和MobileBankingService是Observer。

C++实现上述业务案例的代码如下:

// Observer.h

#include <iostream>

#include <vector>

using namespace std;

class Observer;

//Account抽象类,用做接口

class Account

{

protected:

vector<Observer *> observers;                                      // 保存若干个Observer

double balance;                                                                // 账户余额

public:

virtual void add_observer(Observer *o) = 0;                // 注册一个Observer

virtual void remove_observer(Observer *o) = 0;         // 删除一个Observer

virtual void notify_observer() = 0;                                   // 通知所有注册了的Observer

virtual void set_balance(double balance) = 0;            // 改动账户余额

virtual double get_balance() = 0;                                   // 获取账户月娥

public:

virtual ~Account()

{

cout << "in the destructor of Account..." << endl;

}

};

// Observer抽象类,用做接口

class Observer

{

protected:

Account *account;                                                                      // 账户

public:

Observer(Account *account):account(account)                    // 构造函数

{

}

virtual void handle_event() = 0;                                                // 事件处理

virtual void set_account_balance(double balance) = 0;     // 改动账户余额

virtual ~Observer()

{

cout << "in the destructor of Observer..." << endl;

}

};

// BankAccout具体类,继承Account抽象类

class BankAccount : public Account

{

public:

~BankAccount()

{

cout << "in the destructor of BankAccount..." << endl;

}

public:

void add_observer(Observer *o)

{

observers.push_back(o);

}

void remove_observer(Observer *o)

{

for(vector<Observer *>::iterator it = observers.begin(); it != observers.end(); it++)

{

if(o == *it)                             // 注意*it就是observers中的元素,其类型为Observer *

{

observers.erase(it);  // 这里需要注意,o从observers中被删除,但并未从内存中删除

return;

}

}

}

void notify_observer()                                    // 向observers中的所有Observer发出通知,并进行相关处理

{

for(vector<Observer *>::const_iterator it = observers.begin(); it != observers.end(); it++)

{

(*it)->handle_event();

}

}

void set_balance(double balance)

{

this->balance = balance;

notify_observer();                                  // 只要余额变动,就向所有注册了的Observer发出通知

}

double get_balance()

{

return balance;

}

};

class ATM : public Observer

{

public:

ATM(Account *account):Observer(account)                          // 将account传递给基类Observer的构造函数

{

}

~ATM()

{

cout << "in the destructor of Observer..." << endl;

}

public:

void handle_event()

{

cout << "ATM: The balance of bank account is changed to: " << account->get_balance() << endl;

}

void set_account_balance(double balance)                        // 在ATM中改动银行账户余额,比如在ATM机上存取款

{

account->set_balance(balance);

}

};

class InternetBankingService : public Observer

{

public:

InternetBankingService(Account *account):Observer(account)     // 将account传递给基类Observer的构造函数

{

}

~InternetBankingService()

{

cout << "in the destructor InternetBankingService..." << endl;

}

public:

void handle_event()

{

cout << "IBS: The balance of bank account is changed to: " << account->get_balance() << endl;

}

void set_account_balance(double balance)                                        // 网上银行改动银行账户余额,比如通过网上银行转账

{

account->set_balance(balance);

}

};

class MobileBankingService : public Observer

{

public:

MobileBankingService(Account *account):Observer(account)          // 将account传递给基类Observer的构造函数

{

}

~MobileBankingService()

{

cout << "in the destructor of MobileBankingService..." << endl;

}

public:

void handle_event()

{

cout << "MBS: The balance of bank account is changed to: " << account->get_balance() << endl;

}

void set_account_balance(double balance)                                          // 手机银行改动银行账户余额,比如通过网上银行转账

{

account->set_balance(balance);

}

};

// Observer.cpp

#include "Observer.h"

int main(int argc, char **argv)

{

Account *account = new BankAccount();

Observer *atm_observer = new ATM(account);

Observer *ibs_observer = new InternetBankingService(account);

Observer *mbs_observer = new MobileBankingService(account);

// 注册Observer

account->add_observer(atm_observer);

account->add_observer(ibs_observer);

account->add_observer(mbs_observer);

// 银行账户余额变动(比如在柜台存取款)

account->set_balance(1000.12);

// ATM机触发银行账户余额变动

cout << "\nEvent triggered by atm_observer: " << endl;

cout << "================================" << endl;

atm_observer->set_account_balance(1000.23);

// 网上银行触发银行账户余额变动

cout << "\nEvent triggered by ibs_observer: " << endl;

cout << "================================" << endl;

ibs_observer->set_account_balance(1000.36);

// 手机银行触发银行账户余额变动

cout << "\nEvent triggered by mbs_observer: " << endl;

cout << "================================" << endl;

mbs_observer->set_account_balance(1000.68);

// 删除(unsubscribe)网上银行Observer,并变动银行账户余额

cout << "\nRemove ibs_observer: " << endl;

cout << "====================" << endl;

account->remove_observer(ibs_observer);

account->set_balance(2000.23);

cout << "\nDestroy all dynamically created objects: " << endl;

cout << "========================================" << endl;

delete account;

delete atm_observer;

delete ibs_observer;

delete mbs_observer;

}

运行结果:

ATM: The balance of bank account is changed to: 1000.12

IBS: The balance of bank account is changed to: 1000.12

MBS: The balance of bank account is changed to: 1000.12

Event triggered by atm_observer:

================================

ATM: The balance of bank account is changed to: 1000.23

IBS: The balance of bank account is changed to: 1000.23

MBS: The balance of bank account is changed to: 1000.23

Event triggered by ibs_observer:

================================

ATM: The balance of bank account is changed to: 1000.36

IBS: The balance of bank account is changed to: 1000.36

MBS: The balance of bank account is changed to: 1000.36

Event triggered by mbs_observer:

================================

ATM: The balance of bank account is changed to: 1000.68

IBS: The balance of bank account is changed to: 1000.68

MBS: The balance of bank account is changed to: 1000.68

Remove ibs_observer:

====================

ATM: The balance of bank account is changed to: 2000.23

MBS: The balance of bank account is changed to: 2000.23

Destroy all dynamically created objects:

========================================

in the destructor of BankAccount...

in the destructor of Account...

in the destructor of Observer...

in the destructor of Observer...

in the destructor InternetBankingService...

in the destructor of Observer...

in the destructor of MobileBankingService...

in the destructor of Observer...

Observer设计模式和Mediator设计模式的主要区别

Observer设计模式:某个特定的对象(subject或者observable)的状态发生改变时,其他对象(observers)将做出相应的反应。

Mediator设计模式:任何对象的状态发生变化,其他对象都将做出相应的反应,中间是通过Mediator来进行协调的。

Observer设计模式有一个实际意义上的“中心”。Mediator设计模式没有实际意义上的中心,相对而言更分布式一些,其逻辑上的中心是由于纯设计上的需要而引入的“Mediator”,即Observer模式中,事件源在subject或observable对象;在Mediator模式中,事件源在除Mediator之外的其他所有对象。

关于在STL容器中保存对象指针的情况,详见:

http://patmusing.blog.163.com/blog/static/13583496020101831514657/

 
 
 
 
 

C++实现Behavioral - Observer模式 (转)的更多相关文章

  1. Behavioral模式之Observer模式

    1.意图 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,全部依赖于它的对象都得到通知并被自己主动更新. 2.别名 依赖(dependents).公布-订阅(Publish-Subscr ...

  2. C# 关于委托和事件的妙文:通过一个例子详细介绍委托和事件的作用;Observer模式简介

    委托和事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见 ...

  3. Observer 模式

    Observer模式要解决的问题为:建立一个一(Subject)对多(Observer)的依赖关系,并且做到当“一”变化的时候,依赖这个“一”的多也能够同步改变.最常见的一个例子就是:对同一组数据进行 ...

  4. 【行为型】Observer模式

    观察者模式意图解决一对多的依赖关系情形中,当被依赖对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新的问题.举个很简单的例子说,假如一个游戏中的角色的某个属性状态发生了变化,此处不妨假设为 ...

  5. Java 实现观察者(Observer)模式

    1. Java自带的实现 类图 /** * 观察目标 继承自 java.util.Observable * @author stone * */ public class UpdateObservab ...

  6. 3)Javascript设计模式:Observer模式

    Observer模式 var Observer = (function() { var instance = null; function Observe() { this.events = {} } ...

  7. Java设计模式(20)观察者模式(Observer模式)

    Java深入到一定程度,就不可避免的碰到设计模式(design pattern)这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模式在java的中型系统中应用广泛,遵循 ...

  8. Observer模式实践

    Observer 模式在实践中的应用场景: 为 Point 类设计一个数据绑定机制,当其坐标 x 或 y 被更改时,可以通知外界其更改的过程.将更改过程打印在控制台上.考虑使用松耦合设计. 代码: # ...

  9. 设计模式之——Observer模式

    Observer模式又叫做观察者模式,当观察对象状态发生变化的时候,就会通知给观察者.这种模式适用于根据对象状态进行响应的场景! 实例程序是一个输出数字的程序. 观察者Observer类用于每500m ...

随机推荐

  1. 一般处理程序aspx

    public bool IsReusable { get { return false; } }属性,将该属性的值改为true,为什么不起作用?按照MSDN的解释,该属性的意思是: “获取一个值,该值 ...

  2. 7.Solution的Build、Rebuild和Clean

    大家好,我是原文,这篇随笔是对原文的翻译以及自己的体会. 做程序员没追求的话是永远找不到女朋友的,当然有追求也找不到,这个先不提,好在有追求的时候我是充实而且开心的.现在我们的问题是,每天调试项目,在 ...

  3. swift3.0 项目引导页

    项目引导页并不难,使用 UICollectionView就可以完成, 1.首先获取应用程序的版本号,并存入本地,每次有新版本号,和存入本地的版本号,相比较 fileprivate func setup ...

  4. dao层写展示自己需要注意的问题

    写dao层时一定要把 News news=new News(); 写在while循环内,是每循环一次,new出一个对象

  5. [20190620]日常学习记录(三)-初识promise及vuex

    在学习promise之前重温了Ajax的原生js实现, 在原生js中发送一个http请求首先new XMLHttpRequest() 然后定义状态变更事件 浏览器监听请求的状态,触发不同状态下相应的代 ...

  6. Java中方法的继承以及父类未被子类覆盖的方法调用的问题

    在看java继承这一块的时候发现了一个问题,即父类未被子类覆盖的方法是如何调用的? 是子类拥有了父类的该方法只是没有显示表示,还是子类调用了父类的该方法. 为此做了一下验证 代码如下: public ...

  7. 通过Jenkins调用自动部署war包及jar包到服务器上的Shell脚本

    1)部署war包#!/bin/bashif [ id>0];then echo"stopproject" kill −9 idelse echo "project ...

  8. UWP开发:应用设置存储

    应用设置储存指的是保存在应用程序储存区中的键/值对的字典集合,它自动负责序列化对象,并将其保存在应用程序里.以键/值对方式提供一种快速数据访问的方式,主要用于储存一些应用信息. 1,简介 应用设置是W ...

  9. UVALive 3523 Knights of the Round Table 圆桌骑士 (无向图点双连通分量)

    由于互相憎恨的骑士不能相邻,把可以相邻的骑士连上无向边,会议要求是奇数,问题就是求不在任意一个简单奇圈上的结点个数. 如果不是二分图,一定存在一个奇圈,同一个双连通分量中其它点一定可以加入奇圈.很明显 ...

  10. HTML5新增的音频标签、视频标签

    我们所说的H5就是我们所说的HTML5中新增的语言标准 一.音频标签 在HTML5当中有一个叫做audio的标签,可以直接引入一段音频资源放到我们的网页当中 格式: <audio autopla ...