什么是观察者模式
- 在了解观察者模式之前,先看一个小故事
唐僧师徒四人西天取经,某天,在赶了一上午的路程之后,
唐僧停了下来说:“徒弟们,为师累了,在这休息一会吧。”在这个时候,
孙悟空说:“师傅,你先歇着,我去化斋。”
猪八戒说:“师傅,老猪我留下来保护你。”
沙僧说:“师傅,那我去找点水。”
于是,三个徒弟各自分工干起了自己的事情。
看了上面的小故事后,我们可以看到:在唐僧提出休息后,三个徒弟立马知道自己要干些什么事情。也就是说三个徒弟是通过观察唐僧的一举一动而行事的,在这里唐僧是被观察者,三个徒弟则是观察者。观察者通过被观察者的某个行为而采取某个动作,我们称之为观察者模式。
观察者模式的实现
- 基于上面的小故事,我们现在考虑用代码来实现它。
普通实现方式
1.先定义一个观察者接口,包含一个观察者要做的事情,比如故事中三个徒弟要做的事情
/**
* 观察者接口
*/
public interface Observer{
//观察到动作后要做的事情
public void work();
}
- 分别实现上述接口
public class ShaSeng implements Observer{
@Override
public void work() {
System.out.println("沙僧:师傅,我去打水。");
}
}
public class SunWuKong implements Observer{
@Override
public void work() {
System.out.println("孙悟空:师傅,你先歇着,我去化斋。");
}
}
public class ZhuBaJie implements Observer{
@Override
public void work() {
System.out.println("猪八戒:师傅,我留下来保护你。");
}
}
3.最后给出被观察者(唐僧)类,在内部维护三个观察者(三个徒弟)
public class TangSeng{
Observer sun =new SunWuKong();
Observer zhu =new ZhuBaJie();
Observer sha =new ShaSeng();
public void resting() {
System.out.println("唐僧:为师要休息一下。");
sun.work();
zhu.work();
sha.work();
}
}
4.最后在main方法里调用 new TangSeng().resting();

- 这种写法写起来简单,而且也可以实现功能,但是不够灵活。假如现在要增加一个观察唐僧动作的人,比如妖怪,妖怪看见唐僧停下休息后,就变成老人去骗取唐僧的信任,然后抓住唐僧吃了他。这个时候,我们首先要创建一个观察者“妖怪”,然后在唐僧类中增加这个观察者。
public class Monster implements Observer{
@Override
public void work() {
System.out.println("妖怪:我要去骗取唐僧的信任!");
}
}
public class TangSeng{
Observer sun =new SunWuKong();
Observer zhu =new ZhuBaJie();
Observer sha =new ShaSeng();
Observer monster =new Monster();
public void resting() {
System.out.println("唐僧:为师要休息一下。");
sun.work();
zhu.work();
sha.work();
monster.work();
}
}
- 可以看出,每次新增或者删除观察者,都要修改TangSeng这个被观察者类,非常麻烦,而且还不能做到动态设置观察者数量,每次只能固定,十分不灵活。
使用观察者模式实现
1.和普通方式一样,首先定义观察者接口和三个观察者实现类
/**
* 观察者接口
*/
public interface Observer{
//观察到动作后要做的事情
public void work();
}
public class ShaSeng implements Observer{
@Override
public void work() {
System.out.println("沙僧:师傅,我去打水。");
}
}
public class SunWuKong implements Observer{
@Override
public void work() {
System.out.println("孙悟空:师傅,你先歇着,我去化斋。");
}
}
public class ZhuBaJie implements Observer{
@Override
public void work() {
System.out.println("猪八戒:师傅,我留下来保护你。");
}
}
2.声明一个被观察者抽象类,里面维护一个观察者集合,并对外提供注册以及注销观察者的方法
/**
* 被观察者抽象类
*/
public abstract class Master {
// 执行什么动作时被观察
public abstract void resting();
// 哪些观察者需要观察此对象
private List<Observer> observers = new ArrayList<Observer>();
// 注册观察者
public void add(Observer Observer) {
observers.add(Observer);
}
// 注销观察者
public void delete(Observer Observer) {
observers.remove(Observer);
}
//通知所有观察者
public void notifyObservers() {
for (Iterator iterator = observers.iterator(); iterator.hasNext();) {
Observer Observer = (Observer) iterator.next();
Observer.work();
}
}
}
3.创建一个被观察者
public class TangSeng extends Master{
@Override
public void resting() {
System.out.println("唐僧:为师要休息一下。");
//通知所有观察者
notifyObservers();
}
}
4.main方法调用
public static void main(String[] args) {
//声名一个被观察者
Master tangSeng = new TangSeng();
//声名观察者
Observer sunWuKong = new SunWuKong();
Observer shaSeng = new ShaSeng();
Observer zhuBaJie = new ZhuBaJie();
//注册观察者
tangSeng.add(sunWuKong);
tangSeng.add(zhuBaJie);
tangSeng.add(shaSeng);
//被观察者执行动作
tangSeng.resting();
}
-
使用观察者模式不仅可以灵活注册/注销观察者,而且提升了代码的整体层次,调用者需要几个观察者便注册几个即可。
-
观察者模式是属于比较简单的模式,像Spring框架里的事件监听,就有用到这个模式。
网友评论