详解Java编程的Observer观察者设计模式
作者:Willis Yang 发布时间:2023-11-10 04:06:07
java语言里包含了许多对设计模式的直接支持,如command模式,agent模式,observer模式等。虽然java提供的对这些模式的支持很简单,不能满足比较复杂的应用。但在简单的场景下,使用这些类往往能够得到立杆见影的效果。所以,如果没有什么特殊需求,还是最好利用java的这些类。
Observer模式,又称监听模式,观察者模式,是经典设计模式之一(one of GOF)。java语言中,对这种模式支持的类和接口主要有以下几个,全部来自java.beans包:
java.beans.PropertyChangeListener (interface)
java.beans.PropertyChangeSupport (class)
java.beans.PropertyChangeEvent (class)
java.beans.PropertyChangeListener
这是一个接口,很显然,所有实现这个接口的类就是listener啦(或者叫observer),它会对被监听的对象的某些变化感兴趣。这个接口就一个方法:
public void propertyChange(PropertyChangeEvent evt) {
// TODO Auto-generated method stub
}
接口定义很简单,作用也很明显。接受一个event(被监听者产生的PropertyChangeEvent),然后根据这个event做点反应。
java.beans.PropertyChangeSupport
这个类用在被观察者的类里,用来保存注册的观察者,并负责向他们提供被观察者的变化信息。这个类的方法也不多,不过还是只介绍100%用到的,要不脑子就不够使了,呵呵。
public PropertyChangeSupport(Object sourceBean)
这是构造函数,参数就是被监听者。PropertyChangeListener一般作为被监听者的一个属性。一般如下使用:
private PropertyChangeSupport listeners = new PropertyChangeSupport(this);
注意,这个listeners可不是只代表一个监听者,他可能是一群监听者。那么如何这些listeners是谁呢?这回用到下面的方法了。
public void addPropertyChangeListener(PropertyChangeListener listener)
这个类太容易了,把监听者加进来。就像开 * 一样,记者想要采访,就得先登记一下。显然这个方法可以多次调用(add嘛)。有加就有减:
public void removePropertyChangeListener(PropertyChangeListener listener)
如果这个监听者对被监听者的任何变化多不感兴趣了,就被被监听者赶了出去。
好了,记者都到齐了,被监听者有变化了就该通知人家了,使用如下方法的一个:
public void firePropertyChange(PropertyChangeEvent evt)
public void firePropertyChange(String propertyName,
boolean oldValue,
boolean newValue)
public void firePropertyChange(String propertyName,
int oldValue,
int newValue)
public void firePropertyChange(String propertyName,
Object oldValue,
Object newValue)
实际上,后三个方法的参数都会封装成PropertyChangeEvent,然后调用第一个方法。不过在实际中,我们还是喜欢直接调用后三个中的一个,封装的事我们就不管了。后三个方法的参数都是三个,其中的oldValue和newValue就是改变前后的值,第一个就是给改变一个名字,好让监听者们根据这个名子来做响应。就像开会,政府的所有信息都会被记者听到,但是有的记者只对台湾问题感兴趣,而有的记者对中日问题感兴趣。
对PropertyChangeSupport方法的介绍就这么多吧。注意,PropertyChangeSupport既然被用到了被观察者的类(一般是一个model)里,那么他的这些方法就只在被观察这里调用。
java.beans.PropertyChangeEvent
这个类我也懒得介绍,看看他的主要方法就明白怎么回事了
public String getPropertyName()
public Object getNewValue()
public Object getOldValue()
就者三个类,再有就是具体问题具体分析了。来个例子吧,首先是被观察者:
public class Domain{
protected String id;
protected String name;
protected String desName;
protected PropertyChangeSupport listeners = new PropertyChangeSupport(this);
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
firePropertyChange("Domain.id", null, id);
}
public String getDesName() {
return desName;
}
public void setDesName(String desName) {
this.desName = desName;
firePropertyChange("Domain.desName", null, desName);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
firePropertyChange("Domain.name", null, name);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
listeners.addPropertyChangeListener(listener);
}
public void firePropertyChange(String propName, Object oldValue, Object newValue) {
listeners.firePropertyChange(propName, oldValue, newValue);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
listeners.removePropertyChangeListener(listener);
}
}
有人对Domain的三个属性感兴趣。下面就是这些人中的一个:
public class SimpleObserver implements PropertyChangeListener {
....
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(evt.getPropertyName().equals("Domain.name")){
//do some work
}
}
}
下面是个简单的测试类:
public class SimpleTest{
public static void main(String[] args) {
SimpleObserver observer = new SimpleObserver();
Domain domain = new Domain();
domain.addPropertyChangeListener(observer);
domain.setName("yangsq");
......
}
}
很显然,可以观察到SimpleObserver中propertyChange方法的执行。


猜你喜欢
- 一.背景项目中有个需求大体意思是,上传一个word模板,根据word模板合成word文件,再将word文件转为pdf。二.方案选择1.Spi
- 前言最近做一个微信公众号服务,有一些简单的图片处理功能。主要就是用户在页面操作,前端做一些立刻显示的效果,然后提交保存时后端真正修改原图。从
- utf-8转unicode public static String utf8ToUnicode(String inStr) {
- 参考链接:狂神的Swagger笔记号称世界上最流行的API框架Restful Api 文档在线自动生成器 => API 文档 与API
- 进行数据源或者 FTP 服务器等资源配置时,我们可以将这些配置信息放到一个独立的外部属性文件中,并在 Spring 配置文件中通过形如 ${
- CompletableFuture 介绍CompletableFuture是1.8引入的新特性,一些比较复杂的异步计算场景,尤其是需要串联多
- 水平的ListView-HorizontalListView的使用Android中ListView默认的是竖直方向的滑动,由于项目的需求,需
- 前言:最近工作上遇到几个USB模块在android平台上适配使用的情况,所以要用到USB权限获取问题##USB权限获取有以下2种方式:一、直
- 类和结构的区别:1.一个是引用类型一个是值类型Class是引用类型,继承自System.Object类Struct是值类型,继承自Syste
- 本文实例讲述了C#实现简单合并word文档的方法。分享给大家供大家参考。具体如下:using System;using System.Col
- 前言前面一篇文章分析了 InputReader 对按键事件的流程流程,大致上就是根据配置文件把按键的扫描码(scan code)转换为按键码
- for循环和foreach循环其实可以算得上是从属关系的,即foreach循环是可以转化成for循环,但是for循环不一定能转换成forea
- Service层:public int addUser(UserDomian user){ int i = userMapper
- 前言众所周知,随着Google I/O大会的召开,Google宣布将支持Kotlin作为Android的开发语言,最近几日,关于Kotlin
- using (TransactionScope tr = new TransactionScope()) {
- 1.什么是继承?(1)用来提高代码的复用性(2)将相同的功能模块封装到方法中需要使用时调用方法达到代码复用的目的(3)通过继承将多个类中的相
- 在前面的《基于任务的异步编程模式(TAP)》文章中讲述了.net 4.5框架下的异步操作自我实现方式,实际上,在.net 4.5中部分类已实
- 本文实例汇总了Java的System.getProperty()方法获取信息的用法。分享给大家供大家参考。具体如下:System.out.p
- 此篇文章内容仅限于 描述springboot与 thy 自定义标签的说明,所以你在看之前,请先会使用springboot和thymeleaf
- 我就废话不多说了,大家还是直接看代码吧~using UnityEngine;using System.Collections; public