文档章节

设计模式之观察者模式(二)

o
 osc_w9s1w4o0
发布于 2019/03/29 17:30
字数 1788
阅读 16
收藏 0

精选30+云产品,助力企业轻松上云!>>>

上一篇的观察者模式学习的还好吗?首先简单来回顾下上篇内容,有一个气象站的需求,需要在温度、湿度、气压改变的时候,实时更新三个布告板,以便能及时、准确的获取信息。所以,在设计模式的层面,我们最容易想到并且最正确的方式就是使用观察者模式来处理这个问题。

上一篇,我们通过一系列的分析,并画出符合要求的类图,然后使用了第一种方式,通过自己动手写设计模式实现了观察者模式的功能。但是,截止到目前为止,我们观察者模式的方式都是由被观察者主动发送状态通知给观察者,从而达到实时更新。这样有个弊端就是被观察者不能事先知道观察者每个人的需求,有些观察者其实只需要一点点数据,但无奈会受到一堆数据。有没有方式,让观察者通过getter方法,主动获取新增的状态呢。答案是,有。Java内置的Observer模式两种方法都支持。

java.util包内包含基本的Observer接口与Observable类,这和我们的Subject接口与Observer接口很相似。Observer接口与Observable类使用上更方便。因为许多功能都事先准备好了。你甚至可以使用推(PUSH)或拉(PULL)的方式传送数据。下面就看看,我们修改后的气象站OO设计。 image

Java内置的观察者模式如何运作

Java内置的观察者模式运作方式,和我们在气象站中的实现类似,但有一点小差异。最明显的差异是WeatherData现在扩展自Obserable类,并继承到一些增加、删除、通知观察者的方法(以及其他的方法)。Java版本的用法如下:

如何把对象变成观察者

如同以前一样,实现观察者接口(java.util.Observer),然后调用任何Observable对象的 addObserver()方法。不想再当观察者时,调用deleteObserver()方法即可。

可观察者要如何送出通知

首先,你需要利用扩展java.util.Observable接口产生"可观察者"类 ,然后,需要两个步骤:

  1. 先调用setChanged()方法,标记状态已经改变的事实
  2. 然后调用两种notifyObservers()方法中的一个:notifyObservers()或notifyObservers(Object arg)

观察者如何接收通知

同以前一样,观察者实现了更新的方法,但是方法的签名不太一样: update(Observable o, Object arg) o:主题本身当做第一个变量,好让观察者知道是哪个主题通知它的 arg:这正是传入notifyObservers()的数据对象。如果没有说明,则为空。 如果你想推(push)数据给观察者,你可以把数据当做数据对象传给notifyObservers(arg0)方法。否则,观察者就必须从可观察者对象中拉(pull)数据,如何拉数据,不急不急,我们很快和大家见面。

利用内置的支持重做气象站

首先,把WeatherData改成使用java.util.Observable

package com.dimple.headfirst.observer;

// 1:记得要导入(import)正确的Observer/Observable
import java.util.Observable;

/**
 * 
 * @Title:
 * @Description: 2:我们现在正继承Observable
 * 3:我们不需要追踪观察者了,也不需要管理注册与删除(让超类代劳即可)。
 * 我们把注册、添加、通知的相关代码删除
 */
public class WeatherDataNew extends Observable {
	private float temperature;
	private float humidity;
	private float pressure;
	
	// 4:我们的构造器不再需要为了记住观察者们而建立数据结构了
	public WeatherDataNew() {
		
	}
	
	public void measurementsChanged() {
		// 5: 调用notifyObservers()之前,要先调用setChanged()来指示状态已经改变
		setChanged();
		// 注意:我们没有调用notifyObservers()传送数据对象,这表示我们采用的做法是拉
		notifyObservers();
	}
	
	public void setMeasurements(float temperature, float humidity,float pressure) {
		this.temperature = temperature;
		this.humidity = humidity;
		this.pressure = pressure;
		measurementsChanged();
	}
	
	// 6:这些并不是新方法,只是因为我们要使用“拉”的做法,所以才提醒你有这些方法。观察者会利用这些方法取得WeatherData对象的状态
	public float getTemperature() {
		return temperature;
	}
	
	public float getHumidity() {
		return humidity;
	}
	
	public float getPressure() {
		return pressure;
	}
}

现在,让我们重做CurrentConditionsDisplay

package com.dimple.headfirst.observer;

import java.util.Observable;
// 1:导入正确的Observer/Observable
import java.util.Observer;

/**
 * 
 * @Title:
 * @Description: 2:我们正在实现java.util.Observer接口
 */
public class CurrentConditionDisplayNew implements Observer, DisplayElement {
	
	Observable observable;
	private float temperature;
	private float humidity;
	
	// 3:构造器需要 Observable当参数,并将 CurrentConditionsDisplay对象登记成观察者
	public CurrentConditionDisplayNew(Observable observable) {
		this.observable = observable;
		observable.addObserver(this);
	}

	// 4:改变update方法,增加Observable和数据对象作为参数
	@Override
	public void update(Observable obs, Object arg) {
		// 5:在update()中,先确定可观察者属于WeatherData类型,然后利用getter方法获取温度和湿度测量值,最后调用display() 
		if (obs instanceof WeatherDataNew) {
			WeatherDataNew weatherDataNew = (WeatherDataNew)obs;
			this.temperature = weatherDataNew.getTemperature();
			this.humidity = weatherDataNew.getHumidity();
			display();
		}
	}

	// 显示温度和湿度
	@Override
	public void display() {
		System.out.println("Current conditions: " + temperature + " F degrees and " + humidity + "% humidity");
	}
}

运行新的代码

public class WeatherStation {
	public static void main(String[] args) {
		WeatherDataNew weatherDataNew = new WeatherDataNew();
		CurrentConditionDisplayNew currentConditionDisplayNew = new CurrentConditionDisplayNew(weatherDataNew);
		weatherDataNew.setMeasurements(80, 65, 30.4f);
	}
}

// 结果显示
Current conditions: 80.0 F degrees and 65.0% humidity

至此,我们就把Java内置的观察者模式学习了一遍,你学会了吗?

但是,不知道你发现没有,内置的观察者模式中,可观察者是一个“类”而不是一个“接口”,甚至没有实现一个接口,这样就限制了他的使用和复用,所以还是需要做下强调,提醒大家这是一个“类”的事实。

Observable是一个类

首先,因为Observable是一个“类”,你必须设计一个类继承它。如果某类想同事具有Observable类和另一个超类的行为,就会有纠结,毕竟Java只支持单继承嘛。

Observable将关键的方法保护起来

 protected synchronized void setChanged() {
        changed = true;
    }

setChanged()方法是一个保护方法,这就意味着除非你继承自Observable,否则你无法创建Observable实例并组合到你自己的对象中来。这个设计也就违反了之前第二个设计原则“多用组合,少用继承”。

做什么呢?

如果你能够扩展java.util.Obserable,那么Observable“可能”可以符合你的需求。否则,你可能需要像我们上一篇那样,自己去实现一套观察者模式,不过不管怎样,相信你都已经掌握了观察者模式,这已经难不倒你了。

因为观察者模式是平时使用比较广泛,并且大家会频繁的接触甚至是使用,所以我本来想在这篇进行总结的,考虑到篇幅的原因,让这个总结放到下一篇,通过这两个篇幅的学习和实践,把自己动手写观察者模式以及使用Java内置的方式来使用观察者模式都进行了掌握。其他语言的不知道有没有内置的,只能说Java程序员在看完这篇文章之后,肯定又多了一种选择,给自己鼓掌吧。

PS:代码已经上传,需要查看的朋友点击此处HeadFirstDesign

爱生活,爱学习,爱感悟,爱挨踢

image

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
设计模式视频教程来啦

这是尚学堂科技出的一套关于Java设计模式的视频教程,其实设计模式并不是Java所特有,任何语言都可以根据其原理设计出相应的设计模式来。在设计模式领域有一句话:尽信设计模式不如不信设计模...

storezhang
2013/10/26
294
0
白话设计模式_Index

白话设计模式 【白话设计模式一】简单工厂模式(Simple Factory) 【白话设计模式二】外观模式(Facade) 【白话设计模式三】适配器模式(Adapter) 【白话设计模式四】单例模式(Singleton) 【白话...

浮躁的码农
2017/11/01
42
0
《PHP设计模式大全》系列分享专栏

《PHP设计模式大全》已整理成PDF文档,点击可直接下载至本地查阅 https://www.webfalse.com/read/201739.html 文章 php设计模式介绍之编程惯用法第1/3页 php设计模式介绍之值对象模式第1/5页...

kaixin_code
2018/11/06
244
0
spring 中常用的设计模式

一、 Spring 中常见的设计模式 工厂模式 : BeanFactory 装饰器模式: BeanWrapper 代理模式: AopProxy 单例模式: ApplicationContext 委派模式: DispatcherServlet 策略模式: HandlerMa...

osc_bq1qsg6s
2019/05/21
24
0
设计模式--刘伟(转)

原文:https://blog.csdn.net/lovelion/article/details/17517213 2012年-2013年,Sunny在CSDN技术博客中陆续发表了100多篇与设计模式学习相关的文章,涵盖了七个面向对象设计原则和24个设计...

osc_k5ta3dng
2018/05/16
3
0

没有更多内容

加载失败,请刷新页面

加载更多

自从尝了 Rust,Java 突然不香了

Rust 是软件行业中相对而言比较新的一门编程语言,如果从语法上来比较,该语言与 C++ 其实非常类似,但从另一方面而言,Rust 能更高效地提供许多功能来保证性能和安全。而且,Rust 还能在无需...

osc_k3vwonkw
15分钟前
10
0
Java 高级 面试题 及 参考答案

一、面试题基础总结 1、 JVM结构原理、GC工作机制详解 答:具体参照:JVM结构、GC工作机制详解 ,说到GC,记住两点:1、GC是负责回收所有无任何引用对象的内存空间。 注意:垃圾回收回收的是无...

FH-Admin
15分钟前
14
0
机器学习中的AUC-ROC曲线

作者|ANIRUDDHA BHANDARI 编译|VK 来源|Analytics Vidhya AUC-ROC曲线 你已经建立了你的机器学习模型-那么接下来呢?你需要对它进行评估,并验证它有多好(或有多坏),这样你就可以决定是否...

osc_bg8v9gvf
16分钟前
8
0
音视频(消息)应用场景 :连麦交友例子

实现一个小例子: 效果类似唱吧APP里的 连麦交友功能,音视频,IM 及音视频 SDK参考融云服务商。 没有印象的可以搜索 ’连麦’ 关键字在 应用商店下载一款 连麦的软件 体验下 业务方面的需求...

T型人才追梦者
18分钟前
7
0
逛淘宝天猫想到SSO单点登录

我的原文地址:https://mp.weixin.qq.com/s/77xukPDlgkKnYpwu4LrqaA

osc_yy65eb2q
18分钟前
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部