从新回顾了一下观察者模式,在网上也有很多不错的文章值得学习,本文为个人笔记,mark之用。
1、案例分享
场景:一个时钟对象(被观察对象)每隔1s通知学生(观察者对象),其核心类基于util包下的Observable与Observer
被观察者对象
public class TimeClock extends Observable{
public static final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private String time = formatter.format(new Date());
public TimeClock(){
interval();
}
private void interval(){
Thread thread= new Thread(new Runnable(){
public void run(){
while(true){
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
time = formatter.format(new Date());
System.out.println("time is:"+time);
setChanged();
notifyObservers();
}
}
});
thread.setDaemon(true);
thread.start();
}
public String getTime(){
return time;
}
}
观察者对象
public class Student implements Observer {
private String name;
public Student(String name){
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
System.out.println("student["+this.name+"] 的时间为:"+((TimeClock)o).getTime());
}
}
测试函数
public class Main extends Thread{
public static void main(String[] args){
new Main().start();
}
public void run(){
TimeClock timeClock = new TimeClock();
Student student1= new Student("kevin.yang");
Student student2 = new Student("tonny");
timeClock.addObserver(student1);
timeClock.addObserver(student2);
while(true){
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2、jdk 源码分析
在上述的例子中我们用到了两个非常重要的类/接口
Observer接口
/**
* Observer接口为观察者接口
*/
public interface Observer {
/**
* update()方法,当被观察者对象的状态发生变化时,被观察者对象
* 的notifyObservers()方法就会调用这一方法
*/
void update(Observable o, Object arg);
}
Observable类
public class Observable {
//标示被观察者的状态是否发生变化
private boolean changed = false;
//用于存储观察者的列表
private Vector obs;
public Observable() {
obs = new Vector();
}
/**
* 添加一个观察者到列表
*/
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
/**
* 从列表中删除一个观察者
*/
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
/**
*
*/
public void notifyObservers() {
notifyObservers(null);
}
/**
* 如果本对象发生变化,还原changed状态,调用观察者的
* update方法
*/
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
/**
* 清空观察者列表
*/
public synchronized void deleteObservers() {
obs.removeAllElements();
}
/**
* 设置状态为true,标示对象发生变化
*/
protected synchronized void setChanged() {
changed = true;
}
/**
* 还原状态
*/
protected synchronized void clearChanged() {
changed = false;
}
/**
* 返回changed状态,检测对象是否发生变化
*/
public synchronized boolean hasChanged() {
return changed;
}
/**
* 返回观察者列表的大小
*/
public synchronized int countObservers() {
return obs.size();
}
}