1. 何为观察者模式?
百度百科:
观察者模式是一种对象行为模式。它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。在观察者模式中,主题是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知。
博主理解:当被观察者的状态发生改变时,自动的通知其他的观察者
举个栗子:一个学生在学校里学习,对于学生的家长来说,他们最关心的是学生的成绩,他们希望当孩子的成绩发生改变时,可以及时的通知,进而采取对孩子是奖励或者进行批评教育等行为。
上述的栗子中:
被观察者:学生
被观察者的主要内容:成绩
观察者:家长
需求:当学生的成绩发生改变,家长可以及时被通知,然后根据成绩采取不同的策略
我们如何去解决这个问题呢?如果当观察者突然增多,比如爷爷奶奶也想及时了解到学生的成绩,如何通过简单的方式去解决呢?
解决方案:
- 笨的方案:让家长每 1ms 去查询一下学生的成绩,如果发生变化,就对应采取相应的策略
- 聪明的方案:采用观察者模式,当被观察者的成绩发生改变时,自动的通知其他的观察者
2. 如何实现呢?
2.1 自己编写代码:
UML 图我就不画了,不会画,哈哈(*^_^*),直接上代码!!!
2.1.1 主题接口
public interface Subject {
/**
* 添加观察者
* @param observer 观察者
*/
void addObserver(Observer observer);
/**
* 删除观察者
* @param observer 观察者
*/
void deleteObserver(Observer observer);
/**
* 通知所有的观察者
*/
void notifyObservers();
}
2.1.2 观察者接口
public interface Observer {
/**
* 更新方法
* @param observedSubject 被观察的主题对象
* @param arg 传递的参数
*/
void update(Subject observedSubject, Object arg);
}
2.1.3 被观察者学生类
public class StudentSubject implements Subject{
/**
* 关键集合:保存所有观察者实例对象
*/
private List<Observer> observerList;
/**
* 学生成绩
*/
private float score;
public StudentSubject() {
this.observerList = new ArrayList<>(20);
}
public void changeScore(float score) {
this.score = score;
notifyObservers();
}
@Override
public void addObserver(Observer observer) {
if (!observerList.contains(observer)) {
observerList.add(observer);
}
}
@Override
public void deleteObserver(Observer observer) {
observerList.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observerList) {
observer.update(this, score);
}
}
}
2.1.4 父亲观察者类
public class FatherObserver implements Observer{
@Override
public void update(Subject observedSubject, Object arg) {
if (observedSubject instanceof StudentSubject) {
float score = Float.parseFloat(arg.toString());
if (score >= 60) {
System.out.println("父亲:孩子这次考的还行!成绩:" + score);
}else {
System.out.println("父亲:气死老子了!成绩:" + score);
}
}
}
}
2.1.5 母亲观察者
public class MotherObserver implements Observer {
@Override
public void update(Subject observedSubject, Object arg) {
if (observedSubject instanceof StudentSubject) {
float score = Float.parseFloat(arg.toString());
if (score >= 60) {
System.out.println("母亲:孩子这次考的还行!成绩:" + score);
}else {
System.out.println("母亲:看来不打不行了!成绩:" + score);
}
}
}
}
2.1.6 测试
public class Test {
public static void main(String[] args) {
StudentSubject studentSubject = new StudentSubject();
FatherObserver fatherObserver = new FatherObserver();
MotherObserver motherObserver = new MotherObserver();
studentSubject.addObserver(fatherObserver);
studentSubject.addObserver(motherObserver);
studentSubject.changeScore(59);
// 父亲出差了,暂时不观察孩子了
studentSubject.deleteObserver(fatherObserver);
studentSubject.changeScore(80);
}
}
2.1.7 测试结果
如果还想加入爷爷奶奶他们作为观察者,就分别创建爷爷奶奶的观察者类,然后加入到学生观察者集合里 studentSubject.addObserver(xxx);
2.2 使用 Java 自带工具类:
Java 自带的已经实现了观察者模式的工具类,现在我们看一下,如何用 Java 自带的工具类,写上面这个案例
2.2.1 首先还是创建 StudentSubject 被观察者类,注意,这次是不一样的了!!!
注意:学生主题类直接继承 java.util.Observable 父类
public class StudentSubject extends Observable {
/**
* 学生成绩
*/
private float score;
public void changeScore(float score) {
this.score = score;
setChanged();
notifyObservers(score);
}
}
2.2.2 创建父亲观察者
注意:父亲观察者是实现了 java.util.Observer 类,不是上面自定义的 Observer 类了!!!
public class FatherObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
if (o instanceof StudentSubject) {
float score = Float.parseFloat(arg.toString());
if (score >= 60) {
System.out.println("父亲:孩子这次考的还行!成绩:" + score);
}else {
System.out.println("父亲:气死老子了!成绩:" + score);
}
}
}
}
2.2.3 创建母亲观察者
注意:母亲观察者是实现了 java.util.Observer 类,不是上面自定义的 Observer 类了!!!
public class MotherObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
if (o instanceof StudentSubject) {
float score = Float.parseFloat(arg.toString());
if (score >= 60) {
System.out.println("母亲:孩子这次考的还行!成绩:" + score);
}else {
System.out.println("母亲:看来不打不行了!成绩:" + score);
}
}
}
}
2.2.4 测试
public class Test {
public static void main(String[] args) {
StudentSubject studentSubject = new StudentSubject();
FatherObserver fatherObserver = new FatherObserver();
MotherObserver motherObserver = new MotherObserver();
studentSubject.addObserver(fatherObserver);
studentSubject.addObserver(motherObserver);
studentSubject.changeScore(59);
// 父亲出差了,暂时不观察孩子了
studentSubject.deleteObserver(fatherObserver);
studentSubject.changeScore(80);
}
}
2.2.5 测试截图
注意点:在被观察者通知其他的观察者前要先执行 setChanged(); 方法
至于为什么?咱们看一下源码就知道了,源码是这样的:
setChanged(); 是将 changed 状态改为 true
我们现在看一下,他是如何通知其他的观察者的:
通知其他观察者前要检查 changed 状态,如果为 true 则接着下面的代码走,进行通知,如果为 false 就直接返回!
而且细心的读者能看到 clearChanged(); 这个方法是当 changed 为 true 的时候,在将 changed 赋值为 false,这下明白了吧,如果要进行通知其他的观察者时,首先要调用 setChanged(); 方法,改变父类的 changed 状态为 true
3. 有哪些应用呢?
我现在了解到的,事件监听机制:就是在按钮上绑定一个监听器,当按钮按下的时候,会触发事件,然后执行自定义的处理事件代码,这个实现原理就是使用了观察者模式,其他的还在摸索中,本文到这里也就结束了,如果你们有什么意见可以在下面进行评论,我会一一作出回复,共同进步,加油(●'◡'●)!!!