观察者模式 简述
- 观察者模式又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
- 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
- 观察者设计模式三要素:
- 事件源:触发事件的对象,需要注册监听器
- 监听器:一般设计成接口,由使用者来实现其中的它想要监听的方法
- 事件:触发的事件,里面要封装事件源
- 最后是用户实现监听
开发步骤
- 假设现在要监听学生(Student)小明的学习(study)和睡觉(sleep)情况
事件源
package test.publish;
/**
* Created by Administrator on 2018/7/20 0020.
* 事件源(观察的目标)----下面监听它的study()、 sleep()方法
* 需要注册监听器
*/
public class Student {
/**
* name:学生的普通属性
* bookName:学习的书名
* studentListener:学生监听器
*/
private String name;
private String bookName;
private StudentListener studentListener;
public void study(String bookName) {
this.bookName = bookName;
/** 当注册了监听器时,则实施方法监听
* 监听器方法中含有事件,事件又封装了事件源,而用户实现了监听器
* 所以每次此方法一运行,用户会先监听到,而且能从事件中获取事件源(Student)数据*/
if (studentListener != null) {
studentListener.studyListener(new StudentEven(this));
}
System.out.println("我是 " + name + " ,准备学习 " + bookName);
}
public void sleep() {
/** 当注册了监听器时,则实施方法监听,与上同理*/
if (studentListener != null) {
studentListener.sleepListener(new StudentEven(this));
}
System.out.println("我是 " + name + " ,准备睡觉!");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBookName() {
return bookName;
}
/**
* 注册监听器
* 只要当注册了监听器,才能监听方法
*
* @param studentListener
*/
public void addStudentListener(StudentListener studentListener) {
this.studentListener = studentListener;
}
}
事件
package test.publish;
/**
* Created by Administrator on 2018/7/20 0020.
* 事件---封装事件源,便于事件源对象的传入传出
* 这样的好处是以后用户可以通过触发的事件获取事件源,从而可以获取数据源的数据
*/
public class StudentEven {
private Object evenSource;
public StudentEven(Object evenSource) {
this.evenSource = evenSource;
}
public Object getEvenSource() {
return evenSource;
}
public Student getStudent() {
return (Student) evenSource;
}
}
监听器
package test.publish;
/**
* Created by Administrator on 2018/7/20 0020.
* 监听学生的监听器,通常设计成接口,让用户自己实现
* 用户可以从 StudentEven 中获取事件源
*/
public interface StudentListener {
/**
* 监听器监听的方法
*
* @param studentEven 监听器监听的事件
*/
void studyListener(StudentEven studentEven);
void sleepListener(StudentEven studentEven);
}
用户监听
package test.publish;
/**
* Created by Administrator on 2018/7/20 0020.
* 自己实现监听器,这和使用Java Web的监听器道理是一样的
* 如果只想监听里面的部分方法,则可以再加适配器
*/
public class MyStudentListener implements StudentListener {
@Override
public void studyListener(StudentEven studentEven) {
Student student = studentEven.getStudent();
System.out.println("-----------监听到 " + student.getName() + " 开始学习 " + student.getBookName());
}
@Override
public void sleepListener(StudentEven studentEven) {
Student student = studentEven.getStudent();
System.out.println("-----------监听到 " + student.getName() + " 开始睡觉");
}
}
测试结果
/**
* Created by Administrator on 2018/7/20 0020.
* 未注册监听器时
*/
public class MyTest {
public static void main(String[] args) {
Student student = new Student();
student.setName("小明同学");
student.study("论语");
student.sleep();
}
}
//输出如下
//我是 小明同学 ,准备学习 论语
//我是 小明同学 ,准备睡觉!
//Process finished with exit code 0
/**
* Created by Administrator on 2018/7/20 0020.
* 注册监听后
*/
public class MyTest {
public static void main(String[] args) {
Student student = new Student();
student.setName("小明同学");
student.addStudentListener(new MyStudentListener());
student.study("论语");
student.sleep();
}
}
/*
-----------监听到 小明同学 开始学习 论语
我是 小明同学 ,准备学习 论语
-----------监听到 小明同学 开始睡觉
我是 小明同学 ,准备睡觉!
Process finished with exit code 0
*/