1意图

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

2别名

依赖(Dependents), 发布-订阅(Publish-Subscribe)

3动机

将一个系统分割成一系列相互协作的类有一个常见的副作用:需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,因为这样降低了他们的可重用性。

4实用性

1、当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将二者封装在独立的对象中以使他们可以各自独立的改变和复用。

2、当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象待改变。

3、当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的。

5结构

7优缺点

1、使目标和观察者之间的耦合是抽象的最小的。

2、支持广播通信

3、意外的更新    因为一个观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知。在目标上一个看视无害的操作可能会引起一系列对观察者以及依赖这些观察者的那些对象的更新。此外,如果依赖准则的定义或维护不当,常常会引起错误的更新,这种错误通常很难补捉。

--以上内容来自《可复用面向对向软件的基础》

代码实例:

本例子简单的模拟车辆运行和红绿灯的关系。例子中实现了一个Signallamp的基类(observer),凡是继承这个基类的类都可以观察红绿灯信息,并让(concreteObserver)类Vehicle,继承Signallamp。实现了一个subject的基类,凡是继承subject的concretesubject都可以被继承Signallamp的具体观察者观察,并实现子类TrafficSignal。

在客户端我们实现了几辆车在运行,当红绿灯变化时,有观察红绿灯的车将收影响。如图所以:

这里图片没有说明什么,但可以方便我们想象到客户端场景。许多车在不断的移动,当变成红灯的时候,那些观察TrafficSignal事件的车辆将停止移动,而没有观察该事件的车将不受影响。

1、observer.h中代码如下:

#ifndef _OBSERVER_
#define _OBSERVER_ #include <iostream>
using namespace std; void gotoxy(int x,int y); enum Signallamp{RedSignal, GreenSignal}; class ObserverTrafficSignal{
public:
ObserverTrafficSignal(){}
virtual void updataSignal(Signallamp signal) = ;
}; class Vehicle: public ObserverTrafficSignal{
public:
Vehicle(int px, int py):_pointx(px), _pointy(py){isRed = false;}
void drawVehicle();
void clearVehicle(); void updataposition();
void setmovestep(int stepx, int stepy); virtual void updataSignal(Signallamp signal); private:
int _pointx;
int _pointy;
int _move_x;
int _move_y;
int _save_movex;
int _save_movey;
bool isRed;
}; #endif

observer.h

2、observer.cpp中的代码如下:

#include "observer.h"

#include <iostream>
using namespace std; #include<windows.h> void gotoxy(int x,int y)
{
COORD coord={x,y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
} void conceal_cursor()
{
CONSOLE_CURSOR_INFO cci;
cci.bVisible = false;
cci.dwSize = sizeof(cci);
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorInfo(handle, &cci);
} void Vehicle::drawVehicle()
{
//conceal_cursor(); int i=;
gotoxy(_pointx, _pointy+(i++));
cout<<" __________________";
gotoxy(_pointx, _pointy+(i++));
cout<<"| |";
gotoxy(_pointx, _pointy+(i++));
cout<<"|[_][_][_][_][_][_]|";
gotoxy(_pointx, _pointy+(i++));
cout<<"|o _ _ _ |";
gotoxy(_pointx, _pointy+(i++));
cout<<" `(_)-------(_)(_)-\"";
}
void Vehicle::clearVehicle()
{
int i=;
gotoxy(_pointx, _pointy+(i++));
cout<<" ";
gotoxy(_pointx, _pointy+(i++));
cout<<" ";
gotoxy(_pointx, _pointy+(i++));
cout<<" ";
gotoxy(_pointx, _pointy+(i++));
cout<<" ";
gotoxy(_pointx, _pointy+(i++));
cout<<" ";
} void Vehicle::updataposition()
{
_pointx += _move_x;
_pointy += _move_y;
if(_pointx > )
_pointx = ;
if(_pointy>)
_pointy = ;
if(_pointy<)
_pointy = ;
if(_pointx<)
_pointx = ;
}
void Vehicle::setmovestep(int stepx, int stepy)
{
_move_x = stepx; _move_y = stepy; } void Vehicle::updataSignal(Signallamp signal)
{
switch(signal)
{
case RedSignal:
if(!isRed)
{
isRed = true;
_save_movex = _move_x;
_save_movey = _move_y;
setmovestep(, );
}
break;
case GreenSignal:
if(isRed)
{
setmovestep(_save_movex, _save_movey);
isRed = false;
}
break;
}
}

observer.cpp

代码中updataSignal函数在遇见红灯时,用_save_movex和_save_movey保存了车子原始的移动速度,以便变成绿灯时恢复。

3、subject.h中的代码如下:

#ifndef _SUBJECT_
#define _SUBJECT_ #include <list>
using std::list; #include "observer.h" class subject{
public:
subject(){}
virtual void attach(ObserverTrafficSignal* ob);
virtual void detach(ObserverTrafficSignal* ob);
virtual void notify() = ; list<ObserverTrafficSignal* > _observers; }; class TrafficSignal:public subject{
public:
TrafficSignal():_countTime(),_signal(GreenSignal){}
virtual void notify(); private:
int _countTime;
Signallamp _signal;
}; #endif

subject.h

4、subject.cpp中的代码如下:

#include "subject.h"
#include<iostream>
#include <iterator>
using std::iterator; void subject::attach(ObserverTrafficSignal* ob)
{
if(NULL != ob)
_observers.push_back(ob);
} void subject::detach(ObserverTrafficSignal* ob)
{
if(NULL != ob)
_observers.remove(ob);
} void TrafficSignal::notify()
{
if(!_countTime)
{
_countTime = rand()% + ;
;
if(_signal == RedSignal)
_signal = GreenSignal;
else
_signal = RedSignal;
} _countTime--; gotoxy(, );
if(_signal == RedSignal)
std::cout<<"--红灯--";
else
std::cout<<"--绿色--"; list<ObserverTrafficSignal* >::iterator iter = _observers.begin();
for(iter; iter != _observers.end(); iter++)
{
(*iter)->updataSignal(_signal);
}
}

subject.cpp

代码中notify函数通过随即一个数_countTime的简单的模拟了红绿灯(只有红灯和绿灯),每一次运行将_countTime减一,当_countTime等于零时再次随即一个数,并更好红绿灯。

5、main.cpp中的代码如下:

#include <iostream>
using namespace std;
#include <time.h>
#include "subject.h" int main()
{
srand(time());
Vehicle ve1(, );
ve1.setmovestep(-, ); Vehicle ve2(, );
ve2.setmovestep(-, ); Vehicle ve3(, );
ve3.setmovestep(-, ); TrafficSignal tra;
tra.attach(&ve1);
//tra.attach(&ve2);
tra.attach(&ve3); while()
{
ve1.drawVehicle();
ve2.drawVehicle();
ve3.drawVehicle(); _sleep(); ve1.clearVehicle();
ve2.clearVehicle();
ve3.clearVehicle(); ve1.updataposition();
ve2.updataposition();
ve3.updataposition(); tra.notify();
}
return ;
}

观察者模式(observer)c++实现的更多相关文章

  1. 设计模式 - 观察者模式(Observer Pattern) 详细说明

    观察者模式(Observer Pattern) 详细说明 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...

  2. 设计模式 ( 十六 ) 观察者模式Observer(对象行为型)

    设计模式 ( 十六 ) 观察者模式Observer(对象行为型) 1.概述 一些面向对象的编程方式,提供了一种构建对象间复杂网络互连的能力.当对象们连接在一起时,它们就可以相互提供服务和信息. 通常来 ...

  3. 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)

    原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...

  4. 设计模式 - 观察者模式(Observer Pattern) 详细解释

    观察者模式(Observer Pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...

  5. java设计模式--观察者模式(Observer)

    java设计模式--观察者模式(Observer) java设计模式--观察者模式(Observer) 观察者模式的定义: 定义对象间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖于它的 ...

  6. 观察者模式 Observer 发布订阅模式 源 监听 行为型 设计模式(二十三)

    观察者模式 Observer 意图 定义对象一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖他的对象都得到通知并自动更新. 别名:依赖(Dependents),发布订阅(Publish-Su ...

  7. 8.5 GOF设计模式四: 观察者模式Observer

    GOF设计模式四: 观察者模式Observer  现实中遇到的问题  当有许多不同的客户都对同一数据源感兴趣,对相同的数据有不同的处理方式,该如 何解决?5.1 定义: 观察者模式  观察者模式 ...

  8. 设计模式-观察者模式(Observer Pattern)

    观察者模式(Observer Pattern):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己. 观察者 ...

  9. jQuery中的观察者模式(Observer Pattern)

    在jQuery中,on方法可以为元素绑定事件,trigger方法可以手动触发事件,围绕这2个方法,我们来体验jQuery中的观察者模式(Observer Pattern). ■ on方法绑定内置事件, ...

  10. [Android&amp;Java]浅谈设计模式-代码篇:观察者模式Observer

    观察者,就如同一个人,对非常多东西都感兴趣,就好像音乐.电子产品.Game.股票等,这些东西的变化都能引起爱好者们的注意并时刻关注他们.在代码中.我们也有这种一种方式来设计一些好玩的思想来.今天就写个 ...

随机推荐

  1. codevs 3164 质因数分解

    3164 质因数分解  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description (多数据)给出t个数,求出它的质因子个 ...

  2. Ubuntu 16.04 GNOME无法使用拼音输入法问题

    说明:添加好之后重启!不然会出现输入错乱的问题. 参考: http://forum.ubuntu.org.cn/viewtopic.php?t=477765

  3. JSTL-格式标签库

    主页:http://www.cnblogs.com/EasonJim/p/6958992.html的分支页. 一.<fmt:formatNumber> <fmt:formatNumb ...

  4. GNS3模拟的硬件

    Hardware emulated by GNS3 Cisco 1700 Series 1700s have one or more interfaces on the motherboard, 2 ...

  5. mysql计算两个日期之间的天数

    MYSQL自带函数计算给定的两个日期的间隔天数   有两个途径可获得   1.利用TO_DAYS函数   select to_days(now()) - to_days('20120512')   2 ...

  6. 具体解释Android定位

    相信非常多的朋友都有在APP中实现定位的需求,今天我就再次超炒冷饭,为大家献上国内开发人员经常使用到的三种定位方式.它们分别为GPS,百度和高德,惯例先简介下定位的背景知识. 什么是GPS定位.基站定 ...

  7. java并发编程之Semaphore

    信号量(Semaphore).有时被称为信号灯.是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们可以正确.合理的使用公共资源. 一个计数信号量.从概念上讲,信号量维护了一个许可集.如 ...

  8. 华为OJ:数字颠倒

    将数字转成一个字符串即可了. import java.util.Scanner; public class convertNumber { public static void main(String ...

  9. 容器HashMap原理(学习)

    一.概述 基于哈希表的 Map 接口的非同步实现,允许使用 null 值和 null 键,不保证映射的顺序 二.数据结构 HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体:Has ...

  10. JS的内存空间

    变量对象与引用数据 概念解释 对于基本数据类型Undefined.Null.Boolean.Number.String往往保存在变量对象中 而对于引用数据类型,如Array.String.Object ...