java设计模式之观察者模式

来源:互联网 发布:绝地求生优化设置 编辑:程序博客网 时间:2024/06/13 12:05

全球最大口径射电望远镜启用,中国开始“收听”地外文明声音


人类几千年从来没有停止探索与发现的旅程,从古老的三星堆长长的眼睛面具,到最近刚面试的中国的超级天眼,观察与探索的旅程还在继续。

观察者模式:

又称为发布/订阅模式,它定义了对象之间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都得到通知并被自动更新。

类图如下:


下面我们就以一个生活中的例子来详细解析这个模式,一起来学习下:

小张的老家是有名的蔬菜之乡,邻居都是以蔬菜种植为生的,天气对蔬菜的产量品质影响非常大,小张是大学生,村名们都很仰仗他,想让他用技术手段来检测菜地的温度,当温度达到警戒值的时候自动给村名发送报警信息,村名及时作出防范。


小张思考了很久,决定用java中的观察者模式。

低温预警系统:哪些村民订阅了预警服务,并在气温达到阈值的时候自动通知所有订阅服务的村民

服务订阅者:这里就是指的那些订阅了服务的村民

具体实现:在低温预警系统中存在被观察者也就是村民的对象列表,村民对象含有共同的可以接收通知的方法,我们设计一个观察者接口,这样在预警系统中就可以调用接口方法挨个对订阅的观察者们发送消息了。

public interface ISubject {    /** * 增加观察者 * @param ob * @return */public boolean add(IObserver ob);    /**     * 删除观察者     * @param ob     * @return     */    public boolean remove(IObserver ob);         /**     *通知所有的对象      */    public void notifyAllObserver();        /**     * 设置温度值     * @param tem     */    public void setTemperature(double tem);        /**     * 获取温度预警     */    public String temperatureReport();}public interface IObserver {    public void update(ISubject subject);}import java.util.Iterator;import java.util.Vector;被观察者对象主体public class Subject implements ISubject{private Double temperature;private String warningLev="";/** * 观察者列表 */private Vector<IObserver>vector;public Subject(){vector=new Vector<IObserver>();}/* 增加一个观察者 * @see ISubject#add(IObserver) */public boolean add(IObserver ob) {if(ob!=null&&!vector.contains(ob)){return vector.add(ob);}return false;}public boolean remove(IObserver ob) {return vector.remove(ob);}public void notifyAllObserver() {// TODO Auto-generated method stubIterator<IObserver>iterator=vector.iterator();while(iterator.hasNext()){   (iterator.next()).update(this);}}    private synchronized void invoke()    {    if(this.temperature<10&&this.temperature>5)    {    this.warningLev="低温黄色预警";    }    if(this.temperature>=0&&this.temperature<5)    {    this.warningLev="低温橙色预警";    }    if(this.temperature<0)    {    this.warningLev="低温红色预警";    }        if(!warningLev.equalsIgnoreCase(""))    {    this.notifyAllObserver();    }        }    public synchronized  void setTemperature(double tem) {this.temperature=tem;this.invoke();//设置温度的时候就触发监控事件,通知大家}public synchronized String temperatureReport() {// TODO Auto-generated method stubreturn "当前温度:"+this.temperature+"当前预警:"+this.warningLev;}}村民观察者public class CunminObserver implements IObserver{public void update(ISubject subject) {// TODO Auto-generated method stubSystem.out.println("您收到新的预警消息"+subject.temperatureReport()+",请及时作出防范措施");}}/** * 预警系统 * @author 楚水渔夫@csdn *  */public class TecSystem {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stub        ISubject subject =new Subject();        subject.add(new CunminObserver());//        subject.add(new CunminObserver());//先添加两个村民,后续可以自己再添加        subject.setTemperature(4);         }}

系统运行结果如下,两个村民在气温变化的时候都收到了通知,并及时做了措施,小张的系统很成功。



总结:

第一、观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。

由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。如果被观察者和观察者都被扔到一起,那么这个对象必然跨越抽象化和具体化层次。

第二、观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知,

观察者模式有下面的缺点:

第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

第二、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。

第三、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。

第四、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。





0 0