观察者模式(Observer Pattern)属于行为型模式中的一种,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
当对象间存在一对多关系时,则使用观察者模式。比如:当一个对象被修改,状态发生改变时,则会自动通知它的依赖对象(即观察它的对象)。这是一种被动的观察,不是观察者不停地主动刷新去获取被观察者的状态,而是被观察者的状态发生改变时,去通知它的所有观察者。
模拟baby睡觉,妈妈发现她醒来之后就给她喂奶的过程
一对一的观察
//baby睡觉是一个独立的过程,故将其定义成一个线程任务
class Baby implements Runnable{
Mother m=null;
public Baby(Mather m){
this.m=m;
}
@Override
public void run() {
try {
for(int i=0; i<3; i++){//假设baby睡了三秒
Thread.sleep(1000);
System.out.println("baby is sleeping , "+i+" second");
}
}catch (InterruptedException e) {
e.printStackTrace();
}
cryAndCallDady();//baby醒了,通知妈妈
}
//baby醒来时,通知她的观察者的方法
public void cryAndCallDady(){
System.out.println("baby醒了。。。。。");
m.feetBaby();
}
}
//观察者:妈妈
class Mother{
public void feetBaby(){
System.out.println("喂孩子吃奶");
}
}
public class Test02{
//用于模拟过程的主函数
public static void main(String srgs[]){
Mather m=new Mother();
Baby baby=new Baby(m);
Thread t1 = new Thread(baby);
t1.start();
}
}
//运行结果:
baby is sleeping , 0 second
baby is sleeping , 1 second
baby is sleeping , 2 second
baby醒了。。。。。
喂孩子吃奶
上边的代码组织方式存在很多问题,那就是当有多个观察者的时候,不能灵活的实现,而且,如果多个观察者需要对baby醒来的的这个事件做出不同反应时,每个反应对的方法也不同,还采用上边的模式很难实现,故要做以下修改。
一对多的观察者模式
class Baby implements Runnable{
//保存baby的观察者们
List<Observer> observers=new ArrayList<Observer>();
public void addObserver(Observer obs){
observers.add(obs);
}
@Override
public void run() {
try {
for(int i=0; i<3; i++){
Thread.sleep(1000);
System.out.println("baby is sleeping , "+i+" second");
}
}catch (InterruptedException e) {
e.printStackTrace();
}
wekeUp();//baby醒了,通知观察者们
}
//baby醒来通知每个观察者的方法
public void wekeUp(){
System.out.println("baby醒了。。。。。");
for(Observer obs:observers){
obs.doSomething();
}
}
}
//抽象出一个观察者接口,统一作出反应的方法
interface Observer{
public void doSomething();
}
//不同的观察者对观察现象做自己不同的反应
class Mother implements Observer{
@Override
public void doSomething() {
System.out.println("妈妈:喂孩子吃奶");
}
}
class Grandmother implements Observer{
@Override
public void doSomething() {
System.out.println("奶奶:逗孩子笑");
}
}
class LittleDog implements Observer{
@Override
public void doSomething() {
System.out.println("小狗:汪汪汪。。。");
}
}
public class Test02{
public static void main(String srgs[]){
Baby baby=new Baby();
//添加观察者
baby.addObserver(new Mother());
baby.addObserver(new Grandmother());
baby.addObserver(new LittleDog());
Thread t1 = new Thread(baby);
t1.start();
}
}
//运行结果:
baby is sleeping , 0 second
baby is sleeping , 1 second
baby is sleeping , 2 second
baby醒了。。。。。
妈妈:喂孩子吃奶
奶奶:逗孩子笑
小狗:汪汪汪。。。
上边就是一个常见的观察者模式示例了,如果我们需要针对被观察者也统一规范,可以再抽象出一个对应的接口来,然后让每个被观察者都实现该接口即可。
//被观察事物的抽象接口
interface Subject{
List<Observer> observers=new ArrayList<Observer>();
public void addObserver(Observer obs);//添加观察者
public void delObserver(Observer obs);//删除观察者
public void notify(Observer obs);//通知观察者
}