资讯专栏INFORMATION COLUMN

Java设计模式之观察者模式详解

dayday_up / 881人阅读

摘要:观察者模式,是一对多的关系,一个主题对应多个观察者,当这个主题发生变化的时候,所有观察着这个主题的观察者都会接收到通知来获悉主题的变化。这就是使用的观察者模式,下面就让我们用代码实现观察者模式。

观察者模式,是一对多的关系,一个主题对应多个观察者,当这个主题发生变化的时候,所有观察着这个主题的观察者都会接收到通知来获悉主题的变化。

在现实中我们也会遇到许许多多应用观察者模式的行为,比如电视的节目频道里有时候会有暴雨天气的标志,这个标志是会随着天气的变化来显示,而我们显示的也是最新的天气标志,在这里电视频道就相当于是一个主题,而我们的电视机就是这个主题观察者,所以当这个天气标志有变化时电视上的画面也随着变化。这就是使用的观察者模式,下面就让我们用代码实现观察者模式。

首先我们需要定义主题的接口,这里面有三个方法,registerObserver、removeObserver和notifyObserver,分别是用来添加观察者、去除观察者和通知所有观察者。其中dataChange方法是只要当数据有变化就会被调用,我们需要在这个方法里调用notifyObserver去通知所有的观察者数据变化的内容,这里我们使用setSimulateDataChange方法来模拟数据的变化。

public interface Subject {

    void registerObserver(Observer observer);

    void removeObserver(Observer observer);

    void notifyObserver();
}

然后我们创建一个具体的主题类来实现这个主题接口,假设这个类是获取电视频道的信息。在这个类里面我们需要创建一个集合用来存取观察这个主题的所有观察者,接口中的registerObserver和removeObserver方法实际就是对集合的增删操作,而notifyObserver方法其实就是遍历集合通知所有的对象。

public class TelevisionData implements Subject {
    private String showName;
    private String showType;
    private ArrayList list;

    public TelevisionData(){
        list = new ArrayList();
    }

    @Override
    public void registerObserver(Observer observer) {
        list.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        int index = list.indexOf(observer);
        if (index>=0){
            list.remove(index);
        }
    }

    @Override
    public void notifyObserver() {
        ListIterator listIterator = list.listIterator();
        while (listIterator.hasNext()){
        Observer observer = (Observer)listIterator.next();
            observer.update(showName,showType);
        }
    }

    public void dataChange(){
        notifyObserver();
    }

    //此方法用于模拟控制数据的更新,数据更新后会调用dataChange方法
    public void setSimulateDataChange(String showName,String showType){
         this.showName = showName;
         this.showType= showType;
         dataChange();
    }
}

主题部分的代码写好了,接着我们需要写观察者的代码,电视节目都播放在电视上,那我们把创建的电视类抽取出一个show方法放在Display接口中。

public interface Display {
    void show();
}

另外观察者还有一个共性,就是要接收更新到的数据进行更新,所以我们再抽取出一个update方法放到Obeserver接口中。

public interface Observer {
    void update(String showName,String showNum);
}

最后我们创建观察者的类来实现这两个接口,在这个类中showName和showType字段是用来接收主题的数据的,而subject则是要关注的主题类型引用,通过这个引用我们就可以调用registerObserver和removeObserver来控制观察者是否还要观察这个主题。当主题更新时则会调用update方法,观察者获取到更新的数据就再调用show方法显示出来。

public class John implements Observer,Display {
    private Subject subject;
    private String showName;
    private String showType;

    public John(Subject subject){
        this.subject = subject;
    }

    @Override
    public void show() {
        System.out.println("john收看的当前天气类型-" + showType);
        System.out.println("john收看的当前天气级别-" + showName);
    }

    @Override
    public void update(String showName,String showType) {
        this.showName = showName;
        this.showType = showType;
        show();
    }

    public void registerObserver(){
        this.subject.registerObserver(this);
    }


    public void removeObserver(){
        this.subject.removeObserver(this);
    }
}

public class Jack implements Observer,Display {
    private Subject subject;
    private String showName;
    private String showType;

    public Jack(Subject subject){
        this.subject = subject;
    }

    @Override
    public void show() {
        System.out.println("jack收看的当前天气类型-" + showType);
        System.out.println("jack收看的当前天气级别-" + showName);
    }

    @Override
    public void update(String showName,String showType) {
        this.showName = showName;
        this.showType = showType;
        show();
    }

    public void registerObserver(){
        this.subject.registerObserver(this);
    }


    public void removeObserver(){
        this.subject.removeObserver(this);
    }

}

下面我们来测试一下

//创建一个主题
televisionData = new TelevisionData();
    
//添加观察者
John john = new John(televisionData);
john.registerObserver();
Jack jack = new Jack(televisionData);
jack.registerObserver();
        
//模拟数据更新
changeData("大风", "5级");
changeData("暴雨", "红色");
    
public static void changeData(String showName, String showType) {
    televisionData.setSimulateDataChange(showName,showType);
}

结果:
john收看的当前天气类型-红色
john收看的当前天气级别-暴雨
jack收看的当前天气类型-红色
jack收看的当前天气级别-暴雨
john收看的当前天气类型-5级
john收看的当前天气级别-大风
jack收看的当前天气类型-5级
jack收看的当前天气级别-大风

我们再试着去掉一个观察者看它还会不会收到更新,结果是不会收到更新了

changeData("暴雨", "红色");
john.removeObserver();
changeData("大风", "5级");

结果:
john收看的当前天气类型-红色
john收看的当前天气级别-暴雨
jack收看的当前天气类型-红色
jack收看的当前天气级别-暴雨
jack收看的当前天气类型-5级
jack收看的当前天气级别-大风

总结:
观察者模式的大致原理其实就是观察者持有主题的引用来控制主题内部的集合对自己增删从而控制是否关注这个主题,而主题则通过对集合中的对象的操作,把数据的更新通知给所有的观察者。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/69059.html

相关文章

  • Java学习路线总结,搬砖工逆袭Java架构师(全网最强)

    摘要:哪吒社区技能树打卡打卡贴函数式接口简介领域优质创作者哪吒公众号作者架构师奋斗者扫描主页左侧二维码,加入群聊,一起学习一起进步欢迎点赞收藏留言前情提要无意间听到领导们的谈话,现在公司的现状是码农太多,但能独立带队的人太少,简而言之,不缺干 ? 哪吒社区Java技能树打卡 【打卡贴 day2...

    Scorpion 评论0 收藏0
  • 扔物线:给 Android 开发者的 RxJava 详解

    摘要:观察者模式面向的需求是对象观察者对对象被观察者的某种变化高度敏感,需要在变化的一瞬间做出反应。规定,当不会再有新的发出时,需要触发方法作为标志。在事件处理过程中出异常时,会被触发,同时队列自动终止,不允许再有事件发出。 我从去年开始使用 RxJava ,到现在一年多了。今年加入了 Flipboard 后,看到 Flipboard 的 Android 项目也在使用 RxJava ,并且使...

    tianren124 评论0 收藏0
  • 慕课网_《模式的秘密察者模式》学习总结

    摘要:时间年月日星期二说明本文部分内容均来自慕课网。慕课网教学源码学习源码第一章观察者模式概述课程简介观察者模式的定义定义对象间的一种一对多的依赖关系。 时间:2017年08月29日星期二说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学源码:https://github.com/zccodere/s...学习源码:https://github.com/z...

    iKcamp 评论0 收藏0

发表评论

0条评论

dayday_up

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<