快速引入
观察者模式又名订阅模式,使用率非常高,以至于JDK都内置了实现观察模式所用到的Observer和Observable,这个模式中有两个角色,一个是观察者,一个是被观察者。拿学校中的广播来说,广播发送者是被观察者,而你是观察者,发送一条广播,所有观察者都会知道。
实现
就拿上面的学校广播,我们来实现一个简单的观察者模式的例子。
例子中用到的Observer和Observable请查看我另外一篇文章 Observer与Observable源码解析。本篇文章只讲解使用观察者模式
定义观察者,即学生,观察者需要重写Obsrver接口中的update方法,来进行收到通知后的操作
//定义观察者,观察者需要实现java内置类型Observer
class Student implements Observer {
String name; // 学生姓名
Student(String name) {
this.name = name;
}
// 参数o是订阅者对象,参数arg为收到的通知内容,是一个object(我们这里传String)
@Override
public void update(Observable o, Object arg) {
// TODO Auto-generated method stub
System.out.println(name + "收到了通知,通知内容是:" + arg);
}
}
定义被观察者,即广播,需要写一个方法供调用者调用来发通知,这个方法必须调用setChanged方法,告诉Observable状态已经发生变化了,再调用notifyObservers来更新操作,如果没有调用setChanged而调用notifyObservers是不会发送通知的。
class BroadCast extends Observable {
public void postNewPublication(String content) {
// 状态发生变化
setChanged();
// 通知所有观察者变化内容,参数为object,这里我们传string
notifyObservers(content);
}
}
我来使用一下
public class Test {
public static void main(String[] arg) {
BroadCast broadCast = new BroadCast();
Student xiaoyuan = new Student("小袁");
Student xiaoa = new Student("小阿");
Student xiaohui = new Student("小惠");
// 加入观察者队列中
broadCast.addObserver(xiaoyuan);
broadCast.addObserver(xiaoa);
broadCast.addObserver(xiaohui);
// 发布通知
broadCast.postNewPublication("明天放假三天!");
}
}
会看到输出是这样的
小惠收到了通知,通知内容是:明天放假三天!
小阿收到了通知,通知内容是:明天放假三天!
小袁收到了通知,通知内容是:明天放假三天!
总结
观察者模式中最重要的是对象解耦,将观察者与被观察者隔离,是系统更灵活,可扩展,缺点就是如果一个程序中包括多个观察者,开发调试会复杂,而且默认java中的消息是同步执行的,入股一个观察者出了问题停滞了,就会影响后面的,所以得考虑使用异步。