Observer 观察者
意图
定义对象间的一种一对多的依赖关系 ,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。
动机
一致性,松耦合
需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,因为这样降低了它们的可重用性。
比如:Excel中制作测试数据的折线图、饼状图和柱状图,以直观的表现出性能的变化。在实际操作时,我发现,如果我修改了一个数据,折线图、饼状图和柱状图就都发生了变换。
这一模式中的关键对象是目标(subject)和观察者(observer)。一个目标可以有任意数目的依赖它的观察者。一旦目标的状态发生改变 , 所有的观察者都得到通知。作为对这个通知的响应,每个观察者都将查询目标以使其状态与目标的状态同步。
这种交互也称为发布-订阅(publish-subscribe) 。目标是通知的发布者。它发出通知时并不需知道谁是它的观察者。可以有任意数目的观察者订阅并接收通知。
适用性
在以下任一情况下可以使用观察者模式 :
- 当一个抽象模型有两个方面 , 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
- 当对一个对象的改变需要同时改变其它对象 , 而不知道具体有多少对象有待改变。
- 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之 , 你不希望这些对象是紧密耦合的。
结构
参与者
Subject
- 目标知道它的观察者。可以有任意多个观察者观察同一个目标。
- 提供注册和删除观察者对象的接口。
Observer
- 为那些在目标发生改变时需获得通知的对象定义一个更新接口。
ConcreteSubject
- 将有关状态存入各ConcreteObserver对象。
- 当它的状态发生改变时, 向它的各个观察者发出通知。
ConcreteObserver
- 维护一个指向ConcreteSubject对象的引用。
- 存储有关状态,这些状态应与目标的状态保持一致。
- 实现Observer的更新接口以使自身状态与目标的状态保持一致。
协作
- 当ConcreteSubject发生任何可能导致其观察者与其本身状态不一致的改变时,它将通知它的各个观察者;
- 在得到一个具体目标的改变通知后,ConcreteObserver对象可向目标对象查询信息。ConcreteObserver使用这些信息以使它的状态与目标对象的状态一致。
实现
Subject和Observe都是抽象类,在Subject子类中的ConcreteSubject中实现Attach,Detach以及Notify,Attach,Detach操作的是list<Observe *>,Notify改变state(Observe类中的成员)。ConcreteObserve类中的update函数用来显示更新的状态
#include <iostream>
#include <list>
using namespace std; class Observer
{
public:
virtual void Update(int) = ;
}; class Subject
{
public:
virtual void Attach(Observer *) = ;
virtual void Detach(Observer *) = ;
virtual void Notify() = ;
}; class ConcreteObserver : public Observer
{
public:
ConcreteObserver(Subject *pSubject) : m_pSubject(pSubject){} void Update(int value)
{
cout<<"ConcreteObserver get the update. New State:"<<value<<endl;
} private:
Subject *m_pSubject;
}; class ConcreteObserver2 : public Observer
{
public:
ConcreteObserver2(Subject *pSubject) : m_pSubject(pSubject){} void Update(int value)
{
cout<<"ConcreteObserver2 get the update. New State:"<<value<<endl;
} private:
Subject *m_pSubject;
}; class ConcreteSubject : public Subject
{
public:
void Attach(Observer *pObserver);
void Detach(Observer *pObserver);
void Notify(); void SetState(int state)
{
m_iState = state;
} private:
std::list<Observer *> m_ObserverList;
int m_iState;
}; void ConcreteSubject::Attach(Observer *pObserver)
{
m_ObserverList.push_back(pObserver);
} void ConcreteSubject::Detach(Observer *pObserver)
{
m_ObserverList.remove(pObserver);
} void ConcreteSubject::Notify()
{
std::list<Observer *>::iterator it = m_ObserverList.begin();
while (it != m_ObserverList.end())
{
(*it)->Update(m_iState);
++it;
}
} int main()
{
// Create Subject
ConcreteSubject *pSubject = new ConcreteSubject(); // Create Observer
Observer *pObserver = new ConcreteObserver(pSubject);
Observer *pObserver2 = new ConcreteObserver2(pSubject); // Change the state
pSubject->SetState(); // Register the observer
pSubject->Attach(pObserver);
pSubject->Attach(pObserver2); pSubject->Notify(); // Unregister the observer
pSubject->Detach(pObserver); pSubject->SetState();
pSubject->Notify(); delete pObserver;
delete pObserver2;
delete pSubject;
}
Observer 观察者的更多相关文章
- java: 观察者模式:Observable被观察者,Observer观察者
java: 观察者模式:Observable被观察者,Observer观察者 以房子价格为例,卖房者为被观察者: import java.util.Observable; //被观察者子类化 publ ...
- Java Observer 观察者
http://www.cnblogs.com/jaward/p/3277619.html 1.API 被观察者 java.util.Observable; public class Observabl ...
- Java设计模式——Observer(观察者)模式
在多个对象之间建立一对多的关系,以便当一个对象状态改变的时候.其它全部依赖于这个对象的对象都能得到通知,并被自己主动更新. 适用情况: 当一个抽象模型有两个方面,当中一个方面依赖于还有一方面. 将这二 ...
- 十七、 Observer 观察者设计模式
设计: 代码清单: Observer public interface Observer { void update(NumberGenerator generator); } DigitObserv ...
- Observer观察者设计模式
Observer设计模式主要包括以下两种对象: (1)被观察对象:Subject,它往往包含其他对象感兴趣的东西,上面例子中热水器中就是Subject(被监视对象); (2)观察对象:Observer ...
- Observer(观察者)设计模式[转]
Observer设计模式中主要包括如下两类对象: Subject:监视对象,它往往包含着其他对象所感兴趣的内容.在本范例中,热水器就是一个监视对象,它包含的其他对象所感兴趣的内容,就是tempratu ...
- C#委托与事件之观察者Observer设计模式
前言 委托: 委托是一种在对象里保存方法引用的类型,同时也是一种类型安全的函数指针. 或委托可以看成一种表示函数的数据类型,类似函数指针. 事件是特殊的委托 观察者模式:两种角色:(1)Subj ...
- 设计模式--观察者(Observer)
GOF给出的定义: Define a one-to-many dependency between objects so that when one object changes state, all ...
- 设计模式之Observer(观察者)(转)
Java深入到一定程度,就不可避免的碰到设计模式(design pattern)这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模式在java的中型系统中应用广泛,遵循 ...
随机推荐
- Maven项目导出jar包配置
<!-- 第一种打包方式 (maven-jar-plugin), 将依赖包和配置文件放到jar包外 --> <build> <sourceDirectory>src ...
- RTSP服务器之————rtsp-server(轻量级RTSP / RTP流媒体服务器)
github:https://github.com/revmischa/rtsp-server 轻量级RTSP / RTP流媒体服务器
- Ubuntu安装Nginx 问题以及解决办法
Error1 the HTTP rewrite module requires the PCRE library sudo apt-get update sudo apt-get install li ...
- idea 安装lombok 插件过程
一.作用 Lombok是一个可以通过简单的注解的形式来帮助我们简化消除一些必须有但显得很臃肿的 Java 代码的工具,bean,entity等类,绝大部分数据类类中都需要get.set.toStrin ...
- python学习笔记4--函数/全局变量/递归
一.函数是什么? 函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的,编程中的函数在英文中也有很多不同的叫法.在BASIC中叫做subroutine(子过程或子程序),在Pasc ...
- Java并发编程原理与实战三十五:并发容器ConcurrentLinkedQueue原理与使用
一.简介 一个基于链接节点的无界线程安全队列.此队列按照 FIFO(先进先出)原则对元素进行排序.队列的头部 是队列中时间最长的元素.队列的尾部 是队列中时间最短的元素.新的元素插入到队列的尾部,队列 ...
- 鸟哥的书——ubuntu命令
纯粹按着鸟哥的书上的基本命令打一遍,不喜勿喷! Chapter5.首次登录 一.基础命令: 1.显示时间和日期的命令:date dzhwen@deng:~$ date 2014年 02月 23日 星期 ...
- 可简单避免的三个 JavaScript 发布错误
Web应用程序开发是倾向于在客户端运行所有用户逻辑和交互代码,让服务器暴露REST或者RPC接口.编译器是针对JS作为一个平台,第二版ECMAScript正是考虑到这一点在设计.客户端框架例如Back ...
- 博皮设计:HTML/CSS/Javascript 源码共享
首先感谢 sevennight 对我的大力帮助,由此他也成为了我的第一位园友:其次,由于本人并不了解 HTML/CSS,因此几乎都在 李宝亨 设计的 博皮源码 的基础上进行的修改:最后,为了获得 更加 ...
- js 各类判断用户输入字符的格式函数
1.JS 判断IP格式是否正确: function checkIP(ip) { var regular = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;//正则表达式 if (reg ...