004-行为型-03-观察者模式(Observer)
一、概述
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。
定义了对象之间的一对多依赖,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它的所有依赖者(观察者)都会收到通知并更新。
Observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。
1.1、适用场景
一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
关联行为场景,建立一套触发机制
典型应用
1、侦听事件驱动程序设计中的外部事件
2、侦听/监视某个对象的状态变化
3、发布者/订阅者(publisher/subscriber)模型中,当一个外部事件(新的产品,消息的出现等等)被触发时,通知邮件列表中的订阅者
1.2、优缺点
优点:
- 观察者和被观察者之间建立一个抽象的耦合
- 观察者模式支持广播通信,建立一套触发机制。
缺点:
- 观察者之间有过多的细节依赖、提高时间消耗及程序复杂度
- 使用要得当,要避免循环调用
1.3、类图角色及其职责
1、Subject(被观察者)
被观察的对象。当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。Subject需要维持(添加,删除,通知)一个观察者对象的队列列表。
2、ConcreteSubject
被观察者的具体实现。包含一些基本的属性状态及其他操作。
3、Observer(观察者)
接口或抽象类。当Subject的状态发生变化时,Observer对象将通过一个callback函数得到通知。
4、ConcreteObserver
观察者的具体实现。得到通知后将完成一些具体的业务逻辑处理。
1.4、演进过程
使用:被观察者想要起作用,就必须继承java.util包下的Observable类
构造方法摘要 | |
---|---|
Observable() 构造一个带有零个观察者的 Observable。 |
方法摘要 | |
---|---|
void |
addObserver(Observer o) 如果观察者与集合中已有的观察者不同,则向对象的观察者集中添加此观察者。 |
protected void |
clearChanged() 指示对象不再改变,或者它已对其所有的观察者通知了最近的改变,所以 hasChanged 方法将返回 false。 |
int |
countObservers() 返回 Observable 对象的观察者数目。 |
void |
deleteObserver(Observer o) 从对象的观察者集合中删除某个观察者。 |
void |
deleteObservers() 清除观察者列表,使此对象不再有任何观察者。 |
boolean |
hasChanged() 测试对象是否改变。 |
void |
notifyObservers() 如果 hasChanged 方法指示对象已改变,则通知其所有观察者,并调用 clearChanged 方法来指示此对象不再改变。 |
void |
notifyObservers(Object arg) 如果 hasChanged 方法指示对象已改变,则通知其所有观察者,并调用 clearChanged 方法来指示此对象不再改变。 |
protected void |
setChanged() 标记此 Observable 对象为已改变的对象;现在 hasChanged 方法将返回 true。 |
示例: 监听成员变量变化
public class PersonOrg {
private String name;
private String sex;
private int age; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getSex() {
return sex;
} public void setSex(String sex) {
this.sex = sex;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
}
}
步骤一、监听成员变量name,sex,age的变化,在数值变化是,执行我们的操作,所以Person就是被观察者,所以被观察者必须继承Observable,而Observable中有这三个方法:
1、notifyObservers()
: 如果 hasChanged
方法指示对象已改变,则通知其所有观察者,并调用 clearChanged
方法来指示此对象不再改变。
这个方法是通知观察者被观察者是否改变的,只要hasChanged()方法指示的对象改变,就会调用观察者中的方法。
2、hasChanged()
: 测试对象是否改变。
3、setChanged()
:标记此 Observable 对象为已改变的对象;现在 hasChanged 方法将返回 true。
所以,如果想观察成员变量是否改变,就要在set方法中,执行setChanged()与notifyObservers()
所以,被观察者应该改为:
public class Person extends Observable {
private String name;
private String sex;
private int age; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
this.setChanged();
this.notifyObservers();
} public String getSex() {
return sex;
} public void setSex(String sex) {
this.sex = sex;
this.setChanged();
this.notifyObservers();
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
this.setChanged();
this.notifyObservers();
}
}
步骤二、有了被观察者,就要有观察者,观察者必须实现java.util包下的Observer接口,并重写update(Observable o, Object arg)方法,当被观察者改变时,就会执行update()方法
public class MyObserver implements Observer { @Override
public void update(Observable o, Object arg) {
System.out.println("对象已改变");
}
}
现在,就可以执行看一看了。不过在执行set()方法之前一定要使用addObserver(Observer o)
这个方法注册观察者,不然不会生效。
使用 测试
@Test
public void update() {
Person person = new Person();
//注册观察者
person.addObserver(new MyObserver());
person.setName("小明");
person.setSex("男");
person.setAge(18);
}
输出:
对象已改变
对象已改变
对象已改变
当然可以注册多个观察者
//注册观察者
person.addObserver(new MyObserver());
person.addObserver(new MyObserver());
更多使用:三个方法deleteObserver(Observer o)
,deleteObservers()
,countObservers()
@Test
public void update2() {
Person person = new Person();
//注册观察者
MyObserver myObserver = new MyObserver();
person.addObserver(myObserver);
person.addObserver(new MyObserver());
//获得当前对象已注册的观察者数目
person.countObservers();
//删除指定的一个观察者
person.deleteObserver(myObserver);
//删除该对象全部观察者
person.deleteObservers(); person.setName("小明");
person.setSex("男");
person.setAge(18);
}
二、扩展
2.1、 java.awt.Event
2.2、org.springframework.web.context.request.RequestContextListener、ServletRequestListener、EventListener
监听器是观察者模式的实现一种
2.3、org.springframework.beans.factory.parsing.ReaderEventListener
2.4、google Guava之EventBus
增加pom引入
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>26.0-jre</version>
</dependency>
EventBus是Guava的事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现,在应用中可以处理一些异步任务。对于事件监听和发布订阅模式,EventBus是一个非常优雅和简单解决方案,我们不用创建复杂的类和接口层次结构。
EventBus实际上是一个消息队列,Event Source发送一个消息到EventBus,然后再由EventBus将消息推送到所监听的Listener。
如上述示例使用guava改写
1、创建Listener
可以通过@Subscribe
注解将任意的类的方法变为一个Listener。
public class PersonGuavaListener {
@Subscribe
public void doAction(final String event) {
System.out.println("对象发生变化:" + event);
}
}
2、创建EventBus并发送消息
public class PersonGuava {
EventBus eventBus = new EventBus();
private String name;
private String sex;
private int age; public PersonGuava() {
//注册Listener
eventBus.register(new PersonGuavaListener());
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
//向订阅者发送消息
eventBus.post("Simple Event:name:"+name);
} public String getSex() {
return sex;
} public void setSex(String sex) {
this.sex = sex;
//向订阅者发送消息
eventBus.post("Simple Event:sex:"+sex);
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
//向订阅者发送消息
eventBus.post("Simple Event:age:"+age);
}
}
测试
@Test
public void test() {
PersonGuava person = new PersonGuava();
person.setName("李宏旭");
person.setAge(30);
person.setSex("男");
}
输出
对象发生变化:Simple Event:name:李宏旭
对象发生变化:Simple Event:age:30
对象发生变化:Simple Event:sex:男
由于EventBus是将消息队列放入到内存中的,listener消费这个消息队列,故系统重启之后,保存或者堆积在队列中的消息丢失。
fd
004-行为型-03-观察者模式(Observer)的更多相关文章
- 【设计模式】行为型03观察者模式(Observer Pattern)
记得16年初第一次学习了23种设计模式,但是除了少数几个简单的外,其他的很多都是学了个似懂非懂,以至于有人问起甚至说不上来,现在想想,其实就是没看懂而已.例如观察者模式,其实原理很简单,但是当时并没有 ...
- 设计模式 ( 十六 ) 观察者模式Observer(对象行为型)
设计模式 ( 十六 ) 观察者模式Observer(对象行为型) 1.概述 一些面向对象的编程方式,提供了一种构建对象间复杂网络互连的能力.当对象们连接在一起时,它们就可以相互提供服务和信息. 通常来 ...
- 观察者模式 Observer 发布订阅模式 源 监听 行为型 设计模式(二十三)
观察者模式 Observer 意图 定义对象一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖他的对象都得到通知并自动更新. 别名:依赖(Dependents),发布订阅(Publish-Su ...
- python设计模式---行为型之观察者模式
比较常用咯~~ from django.test import TestCase from abc import ABCMeta, abstractmethod # 行为型设计模式---观察者模式 c ...
- 行为型模式之Observer模式
观察者模式(又被称为发布-订阅模式.模型-视图模式.源-收听者模式或从属者模式) 观察者模式中,一个目标对象管理所有依赖于它的观察者对象,并且在它本身的状态改变时主动发出通知. 应用场景 拍卖会可以认 ...
- 设计模式 - 观察者模式(Observer Pattern) 详细说明
观察者模式(Observer Pattern) 详细说明 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...
- 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)
原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...
- 设计模式 - 观察者模式(Observer Pattern) 详细解释
观察者模式(Observer Pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...
- java设计模式--观察者模式(Observer)
java设计模式--观察者模式(Observer) java设计模式--观察者模式(Observer) 观察者模式的定义: 定义对象间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖于它的 ...
- 8.5 GOF设计模式四: 观察者模式Observer
GOF设计模式四: 观察者模式Observer 现实中遇到的问题 当有许多不同的客户都对同一数据源感兴趣,对相同的数据有不同的处理方式,该如 何解决?5.1 定义: 观察者模式 观察者模式 ...
随机推荐
- AQS的子类在各个同步工具类中的使用情况
AQS AQS(AbstractQueuedSynchronizer)是 java.util.concurrent的基础.J.U.C中宣传的封装良好的同步工具类Semaphore.CountDownL ...
- Java精通并发-死锁检测与相关工具详解
关于死锁其实在之前https://www.cnblogs.com/webor2006/p/10659938.html的jvm学习中已经详细举过例子了,不过这里再来复习一下,另外是从并发这个专题领域的角 ...
- read_excle
Signature: pd.read_excel( ['io', 'sheet_name=0', 'header=0', 'skiprows=None', 'skip_footer=0', 'inde ...
- HDU - 3709 - Balanced Number(数位DP)
链接: https://vjudge.net/problem/HDU-3709 题意: A balanced number is a non-negative integer that can be ...
- LightOJ - 1245 - Harmonic Number (II)(数学)
链接: https://vjudge.net/problem/LightOJ-1245 题意: I was trying to solve problem '1234 - Harmonic Numbe ...
- django 第三天 视图
今日内容 一.url路由分发之include 项目文件夹下的urls.py文件中的url写法: from django.conf.urls import url,include from django ...
- Kafka 通过python简单的生产消费实现
使用CentOS6.5.python3.6.kafkaScala 2.10 - kafka_2.10-0.8.2.2.tgz (asc, md5) 一.下载kafka 下载地址 https://ka ...
- Kubernetes 学习25 创建自定义chart及部署efk日志系统
一.概述 1.我们说过在helm架构中有这么几个关键组件,helm,tiller server,一般托管运行于k8s之上,helm能够通过tiller server在目标k8s集群之上部署应用程序,而 ...
- codevs 1792 分解质因数
1792 分解质因数 题目描述 Description 编写一个把整数N分解为质因数乘积的程序. 输入描述 Input Description 输入一个整数 N 输出描述 Output Descr ...
- 洛谷 P1056 排座椅 题解
P1056 排座椅 题目描述 上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情.不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的 \(D\ ...