Head First Design Patterns学习笔记-观察者模式
认识观察者模式
首先来看看报纸订阅的过程
- 1.报社的业务就是出版报纸
- 2.向某家报社订阅报纸,只要他们有新报纸出版,就会送过来,只要你是他们的订户
- 3.当你不想再看报纸的时候,取消订阅,他们就不会再送新报纸
- 4.只要报社还在运营,就会一直有人来订阅或取消订阅报纸
观察者模式和报纸订阅流程是一样的,只是名字不同。出版社改名为主题(Subject),而订阅者改名为观察者(Observer)
观察者模式的定义
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新。
观察者模式代码
//主题接口
interface Subject {
void registerObserver(Observer o);//增加观察者
void removeObserver(Observer o);//删除观察者
void notifyObservers();//当主题状态改变时,调用此方法通知所有观察者
}
//观察者接口
interface Observer {
void update(float temp); //用来接收主题发送的通知,这里假设主题是温度计,通过接口给观察者发送当前温度
}
//主题实现
class Thermometer implements Subject {
private List<Observer> observers = new ArrayList<>();//观察者集合
private float temp = 0.0f;//温度
public void setTemp(float temp) {//温度更新
this.temp = temp;
notifyObservers();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
if (observers.indexOf(o) >= 0)
observers.remove(o);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temp);
}
}
}
//观察者实现
class ObserverA implements Observer {
@Override
public void update(float temp) {
System.out.println("观察者A:当前的温度是" + temp);
}
}
class ObserverB implements Observer {
@Override
public void update(float temp) {
System.out.println("观察者B:当前的温度是" + temp);
}
}
public class JavaApplication {
public static void main(String[] args) throws Exception{
//具体使用
Thermometer t = new Thermometer();
Observer a = new ObserverA();
Observer b = new ObserverB();
//为a,b注册成为ts的观察者
t.registerObserver(a);
t.registerObserver(b);
//更新温度
t.setTemp(23.00f);
//a不再当观察者
t.removeObserver(a);
//更新温度
t.setTemp(24.00f);
}
}
另外,Java中已经内置了观察者模式,在java.util包下有Observer接口和Observable类
和这里的Subject接口和Observer接口很相似,修改后的代码如下
//主题实现
class Thermometer extends Observable{
private float temp = 0.0f;//温度
public void setTemp(float temp) {//温度更新
this.temp = temp;
setChanged();//说明状态已改变
notifyObservers(temp);
}
}
//观察者实现
class ObserverA implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("观察者A:当前的温度是" + arg);
}
}
class ObserverB implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("观察者B:当前的温度是" + arg);
}
}
public class JavaApplication {
public static void main(String[] args) throws Exception{
//具体使用
Thermometer t = new Thermometer();
Observer a = new ObserverA();
Observer b = new ObserverB();
//为a,b注册成为ts的观察者
t.addObserver(a);
t.addObserver(b);
//更新温度
t.setTemp(23.00f);
//a不再当观察者
t.deleteObserver(a);
//更新温度
t.setTemp(24.00f);
}
}
另外,既然JDK是开源的,那么就顺便去看看JDK的源码中的具体实现
(这里使用的源码版本为jdk1.8.0_74)
Observable对象:(大部分没什么区别的代码就不放出来了)
public Class Observable {
private boolean changed = false;
private Vector<Observer> obs;
...
}
私有成员变量,一个是标志,用于后续判断是否通知观察者,一个观察者集合obs,使用的是Vector容器
标志的用途是用于增加自由度,比如说一秒钟更新10次数据,对于前台显示而言可能不需要这么频繁,那么我们可以自己计数,如果达到10次才设置标志
可以在通知观察者方法源码里看到changed的作用
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();//clearChanged方法里的具体代码就一句:changed = false;
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
而Observer接口更是没什么好说的
public interface Observer {
void update(Observable o, Object arg);
}
相对于我们自己实现的观察者模式,主要区别在于将ArrayList换成了Vector,方法都加上了synchronized关键字来保证线程安全,并没有什么特别的← ←
Head First Design Patterns学习笔记-观察者模式的更多相关文章
- how to design Programs 学习笔记
how to design Programs 学习笔记 */--> how to design Programs 学习笔记 目录 1. 前言 1.1. 系统化程序设计 1.2. 输入和输出 2. ...
- 《Head First 设计模式》学习笔记——观察者模式 + 装饰者模式
装饰者模式是JDK中还有一个使用较多的设计模式,上一个是观察者模式(在Swing中大量使用),业内好的API设计无一离不开常见的设计模式,通常我们所说要阅读源代码,也是为了学习大牛们的设计思路.--- ...
- 学习笔记——观察者模式Observer
观察者模式,当事件发生时,调用相应观察者的方法进行“通知”.Subject中使用一个数据结构存储需要通知的观察者对象,执行Notify时,执行所有观察者的Update方法.
- C#学习笔记-观察者模式
题目1:几个同事为了在上班期间偷偷看休息,做点其他的事情,就和小秘偷偷联系了一下,如果老板回来了,就麻烦小秘偷偷通知一声,这样方便大家及时变更自己的工作状态. 分析: 根据题目分析,首先明确,肯定会有 ...
- Java 学习笔记 观察者模式与适配者模式 监控文件夹
2019.4.12 适配器模式,如果某个类需要实现多个方法,但是开发过程中只需要实现其中的一两个方法,直接使用该类的适配器类,复写需要实现的方法即可 观察者模式:有多个观察者observe观察一个主体 ...
- Fusion360_Generative Design 入门学习笔记
2019.12.17更新 初次见到衍生式设计的时候感觉非常惊艳,现在觉得这个功能就是个弟弟,只能做一些中看不中用的东西.这个方法的理论基础是拓扑优化,想做research的同学可参阅"如何入 ...
- Ant Design Pro 学习笔记:数据流向
在讲这个问题之前,有一个问题应当讲一下: Ant Design Pro / umi / dva 是什么关系? 首先是 umi / dva 的关系. umi 是一个基于路由的 react 开发框架. d ...
- Java-马士兵设计模式学习笔记-观察者模式-模拟Awt Button
一.概述 Java 的Awt是 Observer模式,现用Java自己模拟awt中Button的运行机制 二.代码 1.Test.java import java.text.DateFormat; i ...
- Java-马士兵设计模式学习笔记-观察者模式-AWT简单例子
1.AWT简单例子 TestFrame.java import java.awt.Button; import java.awt.Frame; import java.awt.event.Action ...
随机推荐
- [转载]寻找两个有序数组中的第K个数或者中位数
http://blog.csdn.net/realxie/article/details/8078043 假设有长度分为为M和N的两个升序数组A和B,在A和B两个数组中查找第K大的数,即将A和B按升序 ...
- Android-NDK编译:cocos2d-x(三) eclipse 导入工程
NDK 编译后,用eclipse导入cocos2d-x工程 菜单[File]-->[New]-->[Project] ,弹出New Project 对话框 窗口下方 选 [Android] ...
- MacBook 蓝牙无法搜索设备
背景 经常把MacBook合上盖子就塞进包里,用时打开盖子就继续操作,偶尔会出现刚刚还在用的罗技蓝牙鼠标,重新打开笔记本后就连接不上了,而且也无法搜索到周边的蓝牙设备. 解决方案 快捷键:Option ...
- 使用EntityFramework6连接MySql数据库
准备工具: VS2013.MySQL For VisualStudio 1.1.4.Connector/Net 6.8.3(百度网盘里) 程序包管理器执行命令: Install-Package Ent ...
- BZOJ 1001 [BeiJing2006] 狼抓兔子(平面图最大流)
题目大意 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的.而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: ...
- JavaScript备忘录(3)——正则表达式
正则表达式是用来进行字符串匹配的. 定义正则表达式有两种方法:/wor/或者new RegExp("wor"). 使用方法 在JS中,使用正则表达式的方法有: 字符串的search ...
- MyBatis知多少(5)业务对象模型
几乎所有结构良好的软件都使用了分层设计.分层设计将一个应用程序根据技术职能分为几 个内聚的部分,从而将某种特定技术或接口的实现细节与其他部分分离开来.分层设计可以用任 何一种强壮的编程语言来实现.图1 ...
- Flex知识备忘
div被flex遮挡 //如果设置z-index无效,那么设置flex加载参数 params.wmode = "Opaque";
- (转) IPv6相关RFC
转自http://blog.csdn.net/lucien_cc/article/details/12688477 IPv6 Spec RFC 2460 : Internet Protocol, Ve ...
- Robot Framework自动化测试(二)---元素定位
说明: 不要误认为Robot framework 只是个web UI测试工具,更正确的理解Robot framework是个测试框架,之所以可以拿来做web UI层的自动化是国为我们加入了seleni ...