设计模式之禅——观察者模式

来源:互联网 发布:饥荒 存档 mac steam 编辑:程序博客网 时间:2024/06/12 18:34

观察者模式也叫做发布订阅模式(Publish/subscribe),它是一个经常在项目中使用的模式,定义如下:【定义对象之间一对多的以来关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。

【观察者模式最大的优点就是使得增加观察者和删除观察者变得很容易,然后通知观察者的方式是中断,不是轮询,提高CPU利用率】

例子:李斯让间谍监控韩非子,然后报告给秦始皇

【因为观察者模式非常简单,所以就不多说了,下面 的两个代码一对比就懂了】

我们先来看没有使用观察者模式的时候的样子,直接见代码

UMI图如下:
这里写图片描述

//韩非子接口public interface IHanFeiZi {    //吃早饭    public void haveBreakfast();    //娱乐活动    public void havefun();}
/** * 韩非子 */public class HanFeiZi implements IHanFeiZi {    private boolean isHavingBreakfast = false;    private boolean isHavingFun = false;    @Override    public void haveBreakfast() {        System.out.println("韩非子:开始吃饭了...");        this.isHavingBreakfast = true;    }    @Override    public void havefun() {        System.out.println("韩非子:开始娱乐了...");        this.isHavingFun = true;    }    public boolean isHavingBreakfast(){        return isHavingBreakfast;    }    public void setHavingBreakfast(boolean isHavingBreakfast){        this.isHavingBreakfast = isHavingBreakfast;    }    public boolean isHavingFun(){        return isHavingFun;    }    public void setHavingFun(boolean isHavingFun){        this.isHavingFun = isHavingFun;    }}
//李斯接口public interface IliSi {    public void update(String context);}
public class LiSi implements IliSi{    @Override    public void update(String context) {        System.out.println("李斯:观察到韩非子活动,开始向老板汇报了...");        this.reportToQiShiHuang(context);        System.out.println("李斯:汇报完毕!");    }    private void reportToQiShiHuang(String reportContext){        System.out.println("李斯:报告,秦老板!韩非子有活动了---->" + reportContext);    }}
//间谍,实现Thread接口public class Watch extends Thread {    private HanFeiZi hanFeiZi;    private LiSi liSi;    private String type;    public Watch(HanFeiZi _hanFeiZi, LiSi _liSi, String _type){        this.hanFeiZi = _hanFeiZi;        this.liSi = _liSi;        this.type = _type;    }    @Override    public void run(){        while(true){            if(this.type.equals("breakfast")){                if(this.hanFeiZi.isHavingBreakfast()){                    this.liSi.update("韩非子在吃饭");                    this.hanFeiZi.setHavingBreakfast(false);                }            } else {                if(this.hanFeiZi.isHavingFun()){                    this.liSi.update("韩非子在娱乐");                    this.hanFeiZi.setHavingFun(false);                }            }        }    }}
//场景类public class Client {    public static void main(String[] args) throws InterruptedException {        LiSi liSi = new LiSi();        HanFeiZi hanFeiZi = new HanFeiZi();        Watch watchBreakfast = new Watch(hanFeiZi, liSi, "breakfast");        watchBreakfast.start();        Watch watchFun = new Watch(hanFeiZi, liSi, "fun");        watchFun.start();        hanFeiZi.haveBreakfast();        hanFeiZi.havefun();    }}/**韩非子:开始吃饭了...韩非子:开始娱乐了...李斯:观察到韩非子活动,开始向老板汇报了...李斯:报告,秦老板!韩非子有活动了---->韩非子在吃饭李斯:汇报完毕!李斯:观察到韩非子活动,开始向老板汇报了...李斯:报告,秦老板!韩非子有活动了---->韩非子在娱乐李斯:汇报完毕!*/

ok,简单实现了这个功能之后问题就来了,首先,Watch是一个死循环,非常消耗系统资源。其次,如果除了李斯要监控韩非子之外又有新的人要监控他需要重新修改。

下面使用观察者模式来实现这个例子:
UML图非常简单明了

这里写图片描述

public interface IHanFeiZi {    //吃早饭    public void haveBreakfast();    //娱乐活动    public void havefun();}
//被观察者接口public interface Observable {    //增加一个观察者    public void addObserver(Observer observer);    //删除一个观察者    public void  deleteObserver(Observer observer);    //通知观察者    public void notifyObservers(String context);}
public class HanFeiZi implements IHanFeiZi , Observable{    //定义个变长数组,存放所有的观察者    private ArrayList<Observer> observerList = new ArrayList<>();    @Override    public void haveBreakfast() {        System.out.println("韩非子:开始吃饭了...");        this.notifyObservers("韩非子在吃饭");    }    @Override    public void havefun() {        System.out.println("韩非子:开始娱乐了...");        this.notifyObservers("韩非子在娱乐");    }    @Override    public void addObserver(Observer observer) {        this.observerList.add(observer);    }    @Override    public void deleteObserver(Observer observer) {        this.observerList.remove(observer);    }    @Override    public void notifyObservers(String context) {        for(Observer o : observerList){            o.update(context);        }    }}
//观察者接口public interface Observer {    //一旦发现别人有动静,自己也要行动    public void update(String context);}
//下面是三个观察者//具体的观察者public class LiSi implements Observer {    @Override    public void update(String context) {        System.out.println("李斯:观察到韩非子活动,准备跟老板汇报!");        this.reportToQinshihuang(context);    }    private void reportToQinshihuang(String context){        System.out.println("李斯:报告,秦老板,韩非子有活动了-->" + context);    }}--------------------------------------------------------public class LiuSi implements Observer {    @Override    public void update(String context) {        System.out.println("刘斯:观察到韩非子活动,我也得做出行动!");        this.cry(context);        System.out.println("刘斯: 乐死了...");    }    private void cry(String context){        System.out.println("刘斯: 因为 " + context + ", --所以我快乐");    }}---------------------------------------------------------public class WangSi implements Observer {    @Override    public void update(String context) {        System.out.println("王斯:观察到韩非子活动,我也得做出行动!");        this.cry(context);        System.out.println("王斯: 哭死了...");    }    private void cry(String context){        System.out.println("王斯: 因为 " + context + ", --所以我悲伤");    }}
public class Client {    public static void main(String[] args) {        Observer liSi = new LiSi();        Observer wangSi = new WangSi();        Observer liuSi = new LiuSi();        HanFeiZi hanFeiZi = new HanFeiZi();        hanFeiZi.addObserver(liSi);        hanFeiZi.addObserver(wangSi);        hanFeiZi.addObserver(liuSi);        hanFeiZi.haveBreakfast();    }}/**韩非子:开始吃饭了...李斯:观察到韩非子活动,准备跟老板汇报!李斯:报告,秦老板,韩非子有活动了-->韩非子在吃饭王斯:观察到韩非子活动,我也得做出行动!王斯: 因为 韩非子在吃饭, --所以我悲伤王斯: 哭死了...刘斯:观察到韩非子活动,我也得做出行动!刘斯: 因为 韩非子在吃饭, --所以我快乐刘斯: 乐死了...*/

举一个很简单的例子【可能不太对】,浏览器上开了很多窗口,这个浏览器的主界面就是被观察者,上面新的窗口
这里写图片描述
是被观察者。当你关闭浏览器时,这些个窗口得到通知,关闭掉,当你打开一个新的网页时,添加一个观察者,显示窗口。

7 2
原创粉丝点击