博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
观察者模式(Observer) 又被称"发布-订阅模式"
阅读量:6117 次
发布时间:2019-06-21

本文共 5054 字,大约阅读时间需要 16 分钟。

  hot3.png

一:场景说明

记得上初中时,网络还没有现在这么普及,校门口有个小卖部,我常常到哪里订阅报纸,来关心下“天下大事”(当然不止我一个人订阅啦)

如图订阅报纸流程:

订阅报纸的时候常常遇到几个问题?什么时候出版?出版内容是什么?延迟出版怎么办?谁通知我报纸到了?要我去取报纸?还是会有人送过来?等等

把这样的场景带到我们编程世界里来,我们的解决方案之一就是使用观察者设计模式。

二:观察者模式(Observer),定义对象间的一种一对多的依赖关系。当一个对象的状态或内容发生改变时,所有依赖它的对象都得到通知并被自动更新.

观察者模式的结构说明:

三:代码示例:

其实JDK已经实现的Subject和Observer接口的,我们直接可以使用,下面我会介绍的,这里还是先自己实现下,体会下吧

/** * 观察者接口 * 提供通知更新方法 (可以在这个方法中回调目标对象) * Created by Administrator on 2016/4/22. */public interface Observer {    void update(Subject subject);}

package com.dy.observer;import java.util.ArrayList;import java.util.List;/** * 目标对象 ,作为被观察者 * 它知道观察者,并提供注册和删除观察者 * Created by Administrator on 2016/4/22. */public class Subject {    private List
observerList = new ArrayList<>(); /** * 注册观察者 ,报纸订阅者 * @param observer */ public void attach(Observer observer){ observerList.add(observer); } /** * 删除观察者 * @param observer */ public void detach(Observer observer){ observerList.remove(observer); } /** * 通知所有观察者 * 每当报纸被印出来,及时主动通知所有订阅者,好让他们知道 */ protected void notifyObserver(){ for (Observer observer:observerList){ observer.update(this); } }}

package com.dy.observer;/** * 目标对象的继承者 * 负责具体观察者状态 * 当自己状态变化,通知所有观察者 * Created by Administrator on 2016/4/22. */public class NewsPaper extends Subject {    private String subjectStatus;    /**     * 报纸内容     */    private String content;    public String getSubjectStatus() {        return subjectStatus;    }    public void setSubjectStatus(String subjectStatus) {        this.subjectStatus = subjectStatus;        //状态改变,通知所有观察者        this.notifyObserver();    }    public String getContent() {        return content;    }    public void setContent(String content) {        this.content = content;        //内容有了,说明报纸被印刷出来了,通知所有观察者        this.notifyObserver();    }}

package com.dy.observer;/** * 读者,报纸订阅者 * * 观察者实现类 * 实现更新方法,使自身状态和目标状态保持一致 * Created by Administrator on 2016/4/22. */public class Reader implements Observer {    private String observerStatus;    private String name;    public Reader(String name) {        this.name = name;    }    @Override    public void update(Subject subject) {        //实现更新方法,使自身状态和目标状态保持一致        //采用拉的方式        observerStatus = ((NewsPaper) subject).getSubjectStatus();        System.out.println(name+"收到了报纸,阅读它,内容是:"+((NewsPaper) subject).getContent());    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

package com.dy.observer;/** * Created by Administrator on 2016/4/22. */public class Client {    public static void main(String[] args) {        //报纸被观察者        NewsPaper newsPager = new NewsPaper();        //报纸订阅者,也就是观察者        Reader reader = new Reader("张三");        Reader reader1 = new Reader("李四");        Reader reader2 = new Reader("王二");        //注册订阅者        newsPager.attach(reader);        newsPager.attach(reader1);        newsPager.attach(reader2);        //印刷出报纸内容        newsPager.setContent("本期内容介绍观察者模式");    }}

客户端测试结果:
张三收到了报纸,阅读它,内容是:本期内容介绍观察者模式李四收到了报纸,阅读它,内容是:本期内容介绍观察者模式王二收到了报纸,阅读它,内容是:本期内容介绍观察者模式Process finished with exit code 0

四:使用jdk实现观察者模式

注意修改对应代码

package com.dy.observer.java;import java.util.Observable;/** * Created by Administrator on 2016/4/22. */public class NewsPaper extends Observable {    /**     * 报纸内容     */    private String content;    public String getContent() {        return content;    }    public void setContent(String content) {        this.content = content;        //内容有了,说明报纸被印刷出来了,通知所有观察者        //注意JDK的observer模式的时候,下面这句代码不可少        this.setChanged();        //主动通知,这里用推的方式        this.notifyObservers(this.content);        //如果用的拉的方式,如下代码示例        //this.notifyObservers();    }}

package com.dy.observer.java;import java.util.Observable;import java.util.Observer;/** * 读者,报纸订阅者 * * 观察者实现类 * 实现更新方法,使自身状态和目标状态保持一致 * Created by Administrator on 2016/4/22. */public class Reader implements Observer {    private String name;    public Reader(String name) {        this.name = name;    }    @Override    public void update(Observable o, Object obj) {        System.out.println(name+"收到了报纸,目标推过来的内容是:"+obj);        //拉的方式你自己想想就知道了((NewsPaper) obj).getContent())    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

public class Client {    public static void main(String[] args) {        //报纸被观察者        NewsPaper jdk_subject = new NewsPaper();        //报纸订阅者,也就是观察者        Reader reader = new Reader("张三");        Reader reader1 = new Reader("李四");        Reader reader2 = new Reader("王二");        //注册订阅者        jdk_subject.addObserver(reader);        jdk_subject.addObserver(reader1);        jdk_subject.addObserver(reader2);        //印刷出报纸内容        jdk_subject.setContent("本期内容介绍java JDK实现观察者模式");    }}

王二收到了报纸,目标推过来的内容是:本期内容介绍java JDK实现观察者模式李四收到了报纸,目标推过来的内容是:本期内容介绍java JDK实现观察者模式张三收到了报纸,目标推过来的内容是:本期内容介绍java JDK实现观察者模式Process finished with exit code 0

转载于:https://my.oschina.net/dyyweb/blog/664382

你可能感兴趣的文章
Google最新截屏案例详解
查看>>
2015第31周一
查看>>
2015第31周日
查看>>
在使用EF开发时候,遇到 using 语句中使用的类型必须可隐式转换为“System.IDisposable“ 这个问题。...
查看>>
Oracle 如何提交手册Cluster Table事务
查看>>
BeagleBone Black第八课板:建立Eclipse编程环境
查看>>
在服务器上用Fiddler抓取HTTPS流量
查看>>
文件类似的推理 -- 超级本征值(super feature)
查看>>
【XCode7+iOS9】http网路连接请求、MKPinAnnotationView自定义图片和BitCode相关错误--备用...
查看>>
各大公司容器云的技术栈对比
查看>>
记一次eclipse无法启动的排查过程
查看>>
【转】jmeter 进行java request测试
查看>>
读书笔记--MapReduce 适用场景 及 常见应用
查看>>
SignalR在Xamarin Android中的使用
查看>>
Eclipse和MyEclipse使用技巧--Eclipse中使用Git-让版本管理更简单
查看>>
[转]响应式表格jQuery插件 – Responsive tables
查看>>
8个3D视觉效果的HTML5动画欣赏
查看>>
C#如何在DataGridViewCell中自定义脚本编辑器
查看>>
【linux】crontab定时命令
查看>>
Android UI优化——include、merge 、ViewStub
查看>>