观察者模式 定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
这就好比一个办在线教育的老师(OnlineTeacher)和线下的若干学生(localStudent1, localStudent2, localStudent3 ...)之间的关系。
当这个老师在线上发布了一条消息之后,他所有的学生都会收到通知,并可以根据这条消息的内容来实现对应的更新。
观察者模式类图
为了实现 松耦合 设计,OnlineTeacher对象只需要实现 Subject 接口,并实现其中规定的三个方法即可:
registerObserver(); //注册观察者
removeObserver(); //取消注册观察者
notifyObserver(); //通知观察者
Subject接口:
public interface Subject {
//Subject接口中的三个方法,用于注册、移除和通知observers
void registerObserver(Observer observer);
void removeObserver(Observer observer);
//以上两个方法都需要一个observer对象作为变量,以实现注册或被删除
void notifyObservers();
}
同时,OnlineTeacher对象还需要一个数据结构,来存储已经注册的学生对象。
OnlineTeacher类
public class OnlineTeacher implements Subject {
//建立一个数据结构来存储注册过的observer对象
private ArrayList observerArrayList;
//用message来模拟老师讲课
private String message;
//OnlineTeacher类的构造器,生成该对象时,会初始化一个observerArrayList
public OnlineTeacher() {
observerArrayList = new ArrayList<>();
}
@Override
public void registerObserver(Observer observer) {
observerArrayList.add(observer);
}
@Override
public void removeObserver(Observer observer) {
int i = observerArrayList.indexOf(observer);
if (i > 0) {
observerArrayList.remove(i);
}
}
//实现notifyObservers(),实质上就是遍历observerArrayList,让其中的每一个observer对象调用他们的update()方法
@Override
public void notifyObservers() {
for (int i = 0; i < observerArrayList.size(); i++) {
observerArrayList.get(i).updates(message);
}
}
//OnlineTeacher有一个方法,setMessage()
public void setMessage(String newMessage) {
this.message = newMessage;
messageChanged(); //message赋值之后,调用messageChanged()方法
}
//还有一个方法,messageChanged,在此方法中调用notifyObservers()
public void messageChanged() {
notifyObservers();
}
}
而所有的学生对象只需要实现 Observer 接口即可成为“观察者”。
所有的观察者只需要保有一个OnlineTeacher对象的引用,便可以在各自的构造器中实现对自身的注册。
Observer接口
public interface Observer {
void updates(String message);
}
用来模拟的localStudent对象们
localStudent1类:
public class LocalStudent1 implements Observer {
private Subject onlineTeacher;
//构造器需要OnlineTeacher对象(也就是subject),用来注册自己
public LocalStudent1(Subject onlineTeacher) {
this.onlineTeacher = onlineTeacher;
onlineTeacher.registerObserver(this);
}
@Override
public void updates(String message) {
System.out.println("localStudent1从onlineTeacher那儿得到的message是:" +
message +','+
"我领悟到的是:女子和小人一样");
}
}
localStudent2类:
public class LocalStudent2 implements Observer {
private Subject onlineTeacher;
public LocalStudent2(Subject onlineTeacher) {
this.onlineTeacher = onlineTeacher;
onlineTeacher.registerObserver(this);
}
@Override
public void updates(String message) {
System.out.println("localStudent2从onlineTeacher那儿得到的message是:" +
message +','+
"我领悟到的是:这话还有后半句——近之则不逊,远之则怨");
}
}
localStudent3类:
public class LocalStudent3 implements Observer{
private Subject onlineTeacher;
public LocalStudent3(Subject onlineTeacher) {
this.onlineTeacher = onlineTeacher;
onlineTeacher.registerObserver(this);
}
@Override
public void updates(String message) {
System.out.println("localStudent3从onlineTeacher那儿得到的message是:" +
message +','+
"我领悟到的是:一个人对他亲近了,他对你不尊重,疏远了却又有怨言!");
}
}
运行 ObserverPatternRunDemo.java
public class ObserverPatternRunDemo {
public static void main (String [] args){
OnlineTeacher onlineTeacher = new OnlineTeacher();
LocalStudent1 localStudent1 = new LocalStudent1(onlineTeacher);
LocalStudent2 localStudent2 = new LocalStudent2(onlineTeacher);
LocalStudent3 localStudent3 = new LocalStudent3(onlineTeacher);
onlineTeacher.setMessage("子曰:唯女子与小人难养也");
}
}
运行时,以localStudent1对象为例。生成该对象时,会调用onlineTeacher对象的 registerObserver()方法 ,将其自身加入到onlineTeacher对象的 observerArrayList 当中。
当onlineTeacher对象调用 setMessage("子曰:唯女子与小人难养也"); 时,相当于 message 的值为 子曰:唯女子与小人难养也 。
//OnlineTeacher.java中定义的setMessage()和messageChanged()方法
...
//OnlineTeacher有一个方法,setMessage()
public void setMessage(String newMessage) {
this.message = newMessage;
messageChanged(); //message赋值之后,调用messageChanged()方法
}
//还有一个方法,messageChanged,在此方法中调用notifyObservers()
public void messageChanged() {
notifyObservers();
}
}
...
根据 onlineTeacher 类中定义的方法,应有:
先调用 messageChanged()方法 ,然后会调用 notifyObservers()方法 ,而 notifyObservers() 方法会遍历所有的Observer对象,并调用他们的 update()方法 :
//实现notifyObservers(),实质上就是遍历observerArrayList,让其中的每一个observer对象调用他们的update()方法
@Override
public void notifyObservers() {
for (int i = 0; i < observerArrayList.size(); i++) {
observerArrayList.get(i).updates(message);
}
}
3个localStudent对象的 update()方法 :
localStudent1.update();
@Override
public void updates(String message) {
System.out.println("localStudent1从onlineTeacher那儿得到的message是:" +
message +','+
"我领悟到的是:女子和小人一样");
}
}
localStudent2.update();
@Override
public void updates(String message) {
System.out.println("localStudent2从onlineTeacher那儿得到的message是:" +
message +','+
"我领悟到的是:这话还有后半句——近之则不逊,远之则怨");
}
**localStudent3.update();**
@Override
public void updates(String message) {
System.out.println("localStudent3从onlineTeacher那儿得到的message是:" +
message +','+
"我领悟到的是:一个人对他亲近了,他对你不尊重,疏远了却又有怨言!");
}
Demo运行的结果
localStudent1从onlineTeacher那儿得到的message是:子曰:唯女子与小人难养也,我领悟到的是:女子和小人一样
localStudent2从onlineTeacher那儿得到的message是:子曰:唯女子与小人难养也,我领悟到的是:这话还有后半句——近之则不逊,远之则怨
localStudent3从onlineTeacher那儿得到的message是:子曰:唯女子与小人难养也,我领悟到的是:一个人对他亲近了,他对你不尊重,疏远了却又有怨言!