定义
对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知,并自动更新
观察者模式:定义对象间的一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生改变时,会通知所有观察者对象,使它们能够自动更新自己
JDK内置:
使用JDK中的观察者模式,只能是使用 被观察者类 (Subject) 继承自Observable类,观察者类 实现Observer接口来实现



UML类图:

场景:
* 老师和同学,
* 同学要订阅老师,
* 然后老师发布作业,同学就自动会收到老师的信息
1 采用自己书写的结构:
抽象的被观察者(Subject主题):
package com.duoduo.Observer;
//抽象的被观察者(主题)
public interface Subject {
//注册观察者(关系绑定)
public void registerObserver(Observer observer);
//移除观察者
public void removeObserver(Observer observer);
//通知观察者更新
public void notifyObserver();
}
具体被观察者:
package com.duoduo.Observer;
import java.util.ArrayList;
public class TeacherSubject implements Subject{
//装载观察者的容器
private final ArrayList<Observer> mObservers;
private String mWork;
public TeacherSubject() {
mObservers=new ArrayList<>();
}
@Override
public void registerObserver(Observer observer) {
mObservers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
if(mObservers.indexOf(observer)>=0) {
mObservers.remove(observer);
}
}
@Override
public void notifyObserver() {
for(Observer o : mObservers) {
o.update(mWork);
}
}
public void setHomework(String work) {
this.mWork=work;
System.out.println("老师: 今天作业是------"+work);
this.notifyObserver();
}
}
抽象Observer:
package com.duoduo.Observer;
//观察者 定义更新接口
public interface Observer {
public void update(String work);
}
具体observer:
package com.duoduo.Observer;
//具体的观察者们 实现观察者接口的定义更新方法
public class StudentObserver implements Observer{
private final Subject msubject;
private String mName;
private String mWork;
public StudentObserver(String name,Subject subject) {
this.mName=name;
this.msubject=subject;
this.msubject.registerObserver(this); //注册观察者
}
@Override
public void update(String work) {
System.out.println("学生----"+mName+"------今天作业是----"+work);
}
}
测试:
/*
* 老师和同学,
* 同学要订阅老师,
* 然后老师发布作业,同学就自动会收到老师的信息
*/
public class ObserverActivity {
public static void main(String [] args) {
System.out.println("观察者模式开始:");
TeacherSubject teacherSubject=new TeacherSubject();
StudentObserver d1=new StudentObserver("张1",teacherSubject);
StudentObserver d2=new StudentObserver("张2",teacherSubject);
StudentObserver d3=new StudentObserver("张3",teacherSubject);
teacherSubject.setHomework("第1页第一题");
teacherSubject.setHomework("第2页第一题");
teacherSubject.setHomework("第3页第一题");
}
}
结果:
顺序无所谓~可以明显看出有一个更新的过程~

2 采用JDK 内置接口/类:
package com.duoduo.Observer;
import java.util.Observable;
import java.util.Observer;
//具体的观察者们 实现观察者接口的定义更新方法
public class StudentObserver implements Observer{
private Observable msubject;
private String mName;
private String mWork;
//构造器
public StudentObserver(String name, Observable subject) {
this.mName=name;
this.msubject=subject;
msubject.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
if(o instanceof TeacherSubject) {
this.mWork=(String) arg;
System.out.println("学生----"+mName+"------今天作业是----"+mWork);
}
}
}
主题类:
package com.duoduo.Observer;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
public class TeacherSubject extends Observable{
private String mWork;
public void setHomework(String work) {
this.mWork=work;
System.out.println("老师: 今天作业是------"+work);
setChanged();
notifyObservers();
}
}
测试:
package com.duoduo.Observer;
/*
* 老师和同学,
* 同学要订阅老师,
* 然后老师发布作业,同学就自动会收到老师的信息
*/
public class ObserverActivity {
public static void main(String [] args) {
System.out.println("观察者模式开始:");
TeacherSubject teacherSubject=new TeacherSubject();
StudentObserver d1=new StudentObserver("张1",teacherSubject);
StudentObserver d2=new StudentObserver("张2",teacherSubject);
StudentObserver d3=new StudentObserver("张3",teacherSubject);
teacherSubject.setHomework("第1页第一题");
teacherSubject.setHomework("第2页第一题");
teacherSubject.setHomework("第3页第一题");
}
}

观察者模式的特点:
将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象间的一致性。
我们不希望为了维护一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。
观察者模式的关键对象是主题Subject和观察者Observer,一个Subject可以有任意数目的依赖它的Observer,一旦Subject的状态发生改变,所有的Observer都可以得到通知。Subject发出通知时并不需要知道谁是它的观察者,也就是说,具体观察者是谁它根本不需要知道。而任何一个具体观察者不知道也不需要知道其他观察者的存在。
使用场景:
1、当一个对象的改变需要同时改变其他对象,并且它不知道具体有多少对象有待改变时,应考虑使用观察者模式;
2、一个抽象模型有两个方面,其中一方面依赖与另一方面,这是观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。
总的来讲,观察者模式所做的工作其实就是在解除耦合,让耦合的双方都依赖于抽象,而不是依赖于具体,从而使得各自的变化都不会影响另一边的变化。
优点
观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。
缺点
依赖关系并未完全解除,抽象通知者依旧依赖抽象的观察者。
改进
使用事件和委托来改进
注意:
Observer是一个接口,而Observable是一个类,在使用时必须继承它,因此在继承Observable时就无法再继承其他超类了,因为Java毕竟不支持多重继承。且在Observable更新前,即notifyObservers()或notifyObservers(Object arg)前要先调用setChanged()标记更新状态

被折叠的 条评论
为什么被折叠?



