java设计模式-----9、观察者模式
Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。
Observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。
观察者模式的结构
观察者模式的角色和职责
1、Subject(被观察者)
被观察的对象。当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。Subject需要维持(添加,删除,通知)一个观察者对象的队列列表。
2、ConcreteSubject
被观察者的具体实现。包含一些基本的属性状态及其他操作。
3、Observer(观察者)
接口或抽象类。当Subject的状态发生变化时,Observer对象将通过一个callback函数得到通知。
4、ConcreteObserver
观察者的具体实现。得到通知后将完成一些具体的业务逻辑处理。
而被观察者想要起作用,就必须继承java.util包下的Observable类,这是它的方法,后面会有介绍
构造方法摘要 | |
---|---|
Observable() 构造一个带有零个观察者的 Observable。 |
方法摘要 | |
---|---|
void |
addObserver(Observer o) 如果观察者与集合中已有的观察者不同,则向对象的观察者集中添加此观察者。 |
protected |
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 |
setChanged() 标记此 Observable 对象为已改变的对象;现在 hasChanged 方法将返回 true。 |
下面写一个例子:新建一个Person类
public class Person {
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就是被观察者,所以server必须继承Observable,而Observable中有这三个方法:
1、notifyObservers()
: 如果 hasChanged
方法指示对象已改变,则通知其所有观察者,并调用 clearChanged
方法来指示此对象不再改变。
这个方法是通知观察者被观察者是否改变的,只要hasChanged()方法指示的对象改变,就会调用观察者中的方法。
2、hasChanged()
: 测试对象是否改变。
3、setChanged()
:标记此 Observable 对象为已改变的对象;现在 hasChanged 方法将返回 true。
所以,如果想观察成员变量是否改变,就要在set方法中,执行setChanged()与notifyObservers()
所以,被观察者应该改为:
import java.util.Observable; 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()方法
import java.util.Observable;
import java.util.Observer; public class MyObserver implements Observer { @Override
public void update(Observable o, Object arg) {
System.out.println("对象已改变");
} }
现在,就可以执行看一看了。不过在执行set()方法之前一定要使用addObserver(Observer o)
这个方法注册观察者,不然不会生效。
public class MainClass {
public static void main(String[] args) {
Person person = new Person();
//注册观察者
person.addObserver(new MyObserver());
person.setName("小明");
person.setSex("男");
person.setAge(18);
}
}
输出结果是这样的:
对象已改变
对象已改变
对象已改变
同时,notifyObservers()为什么是s结尾呢,因为我们可以同时注册多个观察者,这样写
public class MainClass {
public static void main(String[] args) {
Person person = new Person();
//注册观察者
person.addObserver(new MyObserver());
person.addObserver(new MyObserver()); person.setName("小明");
person.setSex("男");
person.setAge(18);
}
}
我们注册两个观察者,两个都会生效,结果就变为了:
对象已改变
对象已改变
对象已改变
对象已改变
对象已改变
对象已改变
还有三个方法deleteObserver(Observer o)
,deleteObservers()
,countObservers()
public class MainClass {
public static void main(String[] args) {
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);
}
}
观察者模式的典型应用
1、侦听事件驱动程序设计中的外部事件
2、侦听/监视某个对象的状态变化
3、发布者/订阅者(publisher/subscriber)模型中,当一个外部事件(新的产品,消息的出现等等)被触发时,通知邮件列表中的订阅者
最新文章
- DateTable利用NPOI导出Excel 公共方法
- Ext-设置form表单不可编辑
- LintCode Binary Tree Inorder Traversal
- Thwarting Buffer Overflow Attacks Stack Randomization
- timeit统计运行时间
- [Android]Log打印
- Android 如何在Java代码中手动设置控件的marginleft
- Linux 自动更新时间
- 1.0 Python 学习网站
- vue 项目中实用的小技巧
- 51Nod--1008
- Spring完全基于Java配置和集成Junit单元测试
- 【原】javascript笔记之Array方法forEach&;map&;filter&;some&;every&;reduce&;reduceRight
- DFA确定有限状态自动机
- HTML词法和语法
- 第五节:Task构造函数之TaskCreationOptions枚举处理父子线程之间的关系。
- ORACLE数据库找回用户密码
- C语言 实现逆置功能
- (线性结构dp )POJ 1260 Pearls
- MySQL 5.6新特性 -- Index Condition Pushdown
热门文章
- USB-Redirector-Technician 永久破解版(USB设备映射软件)
- centos绑定https
- Azure CLI2.0 捕获Linux ARM非托管磁盘虚拟机并创建ARM托管磁盘虚拟机
- react onclick传递参数
- docker微服务部署之:三,搭建Zuul微服务项目
- Mysql 四种事务隔离介绍以及锁机制
- ";[Vue warn]: Failed to mount component: template or render function not defined";错误的解决
- Access to the path ‘’ is denied
- 2018南京网络赛 - Skr 回文树
- 【性能测试】:LR中解决接口请求中包含中文字符,服务器不识别的问题