设计模式之观察者模式

来源:互联网 发布:开源java web绘图工具 编辑:程序博客网 时间:2024/05/29 19:34

观察者模式(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 secondbaby is sleeping , 1 secondbaby is sleeping , 2 secondbaby醒了。。。。。喂孩子吃奶

上边的代码组织方式存在很多问题,那就是当有多个观察者的时候,不能灵活的实现,而且,如果多个观察者需要对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 secondbaby is sleeping , 1 secondbaby is sleeping , 2 secondbaby醒了。。。。。妈妈:喂孩子吃奶奶奶:逗孩子笑小狗:汪汪汪。。。

上边就是一个常见的观察者模式示例了,如果我们需要针对被观察者也统一规范,可以再抽象出一个对应的接口来,然后让每个被观察者都实现该接口即可。

//被观察事物的抽象接口interface Subject{    List<Observer> observers=new ArrayList<Observer>();    public void addObserver(Observer obs);//添加观察者    public void delObserver(Observer obs);//删除观察者    public void notify(Observer obs);//通知观察者}