博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
观察者模式
阅读量:5972 次
发布时间:2019-06-19

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

观察者模式的定义:

定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。

观察者模式的类图:

1200369-20180412161351508-1269189510.png

根据类图自定义主题、观察者接口:

package observer;/** * 主题接口 * @author 发挥哥 * */public interface Subject {    /**     * 注册观察者     * @param observer 观察者对象     */    void registerObserver(Observer observer);    /**     * 移除观察者     * @param observer 观察者对象     */    void removeObserver(Observer observer);    /**     * 通知所有观察者     */    void notifyObservers();}
package observer;/** * 观察者接口 * @author 发挥哥 * */public interface Observer {    /**     * 主题通知所有观察者,执行该方法     * @param msg     */    void update(String msg);}

创建主题类和观察者类:

package observer;import java.util.ArrayList;import java.util.List;import observer.Subject;/** * 自定义主题类,实现自定义主题接口 * @author 发挥哥 * */public class TestSubject implements Subject {    /**     * 所有注册到该主题的观察者     */    private List
observers=new ArrayList<>(); /** * 主题的状态 */ private String msg; @Override public void registerObserver(Observer observer) { // TODO Auto-generated method stub if(observers!=null&&observer!=null) observers.add(observer); } @Override public void removeObserver(Observer observer) { // TODO Auto-generated method stub if(observers.contains(observer)) { observers.remove(observer); } } @Override public void notifyObservers() { // TODO Auto-generated method stub observers.stream().forEach(observer->{ observer.update("主题更新了,大家注意:"+this.msg); }); } /** * 编辑主题的状态后,通知所有观察者 * @param msg */ public void editMsg(String msg) { this.msg = msg; notifyObservers(); }}
package observer;/** * 观察者1 * @author 发挥哥 * */public class Test1Observer implements Observer {    /**     * 创建观察者对象时,将其注册到指定的主题     * @param subject     */    public Test1Observer(Subject subject) {        subject.registerObserver(this);    }    /**     * 当主题状态变化时,通过调用该方法通知观察者     */    @Override    public void update(String msg) {        // TODO Auto-generated method stub        System.out.println(this.getClass().getName()+"收到主题发来的消息:"+msg);    }}
package observer;/** * 观察者2(仅为测试,实现与观察者1一样) * @author 发挥哥 * */public class Test2Observer implements Observer {        public Test2Observer(Subject subject) {        subject.registerObserver(this);    }    @Override    public void update(String msg) {        // TODO Auto-generated method stub        System.out.println(this.getClass().getName()+"收到主题发来的消息:"+msg);    }}

创建测试方法:

package observer;public class TestMain {    public static void main(String[] args) {        //创建主题        TestSubject subject=new TestSubject();        //创建观察者1并注册到主题        Observer observer1=new Test1Observer(subject);        //创建观察者2并注册到主题        Observer observer2=new Test2Observer(subject);        //主题进行2次状态修改        subject.editMsg("第一次调整!");        subject.editMsg("第二次调整!");    }}

测试结果如下:

observer.Test1Observer收到主题发来的消息:主题更新了,大家注意:第一次调整!

observer.Test2Observer收到主题发来的消息:主题更新了,大家注意:第一次调整!
observer.Test1Observer收到主题发来的消息:主题更新了,大家注意:第二次调整!
observer.Test2Observer收到主题发来的消息:主题更新了,大家注意:第二次调整!

以上是自定义主题和观察者接口及其实现,JDK中已经帮我们实现了观察者模式,借助于java.util.Observable和java.util.Observer:

package java.util;public class Observable {    private boolean changed = false;    private Vector
obs; public Observable() { obs = new Vector<>(); } public synchronized void addObserver(Observer o) { if (o == null) throw new NullPointerException(); if (!obs.contains(o)) { obs.addElement(o); } } public synchronized void deleteObserver(Observer o) { obs.removeElement(o); } public void notifyObservers() { notifyObservers(null); } public void notifyObservers(Object arg) { Object[] arrLocal; synchronized (this) { if (!changed) return; arrLocal = obs.toArray(); clearChanged(); } for (int i = arrLocal.length-1; i>=0; i--) ((Observer)arrLocal[i]).update(this, arg); } public synchronized void deleteObservers() { obs.removeAllElements(); } protected synchronized void setChanged() { changed = true; } protected synchronized void clearChanged() { changed = false; } public synchronized boolean hasChanged() { return changed; } public synchronized int countObservers() { return obs.size(); }}
package java.util;public interface Observer {    void update(Observable o, Object arg);}

类java.util.Observable和接口java.util.Observer比较简单,直接借此创建主题和观察者类:

package observer.jdk;import java.util.Observable;/** * 主题1 * @author 发挥哥 * */public class MySubject extends Observable {    private String msg;    /**     * 编辑主题消息,并将变动标志置true,通知所有观察者,再将标志置false     * @param msg     */    public void editMsg(String msg) {        if(msg==null) {            this.msg = msg;            setChanged();            notifyObservers("主题将消息置空!");            clearChanged();            return;        }        if(this.msg!=null&&msg!=null&&this.msg.equals(msg)) {            return;        }                 this.msg = msg;        setChanged();        notifyObservers("主题更新消息:"+this.msg);        clearChanged();         }}
package observer.jdk;import java.util.Observable;/** * 主题2(仅为测试,与观察者1实现一样) * @author 发挥哥 * */public class OtherSubject extends Observable {    private String msg;    public void editMsg(String msg) {        if(msg==null) {            this.msg = msg;            setChanged();            notifyObservers("主题将消息置空!");            clearChanged();            return;        }        if(this.msg!=null&&msg!=null&&this.msg.equals(msg)) {            return;        }                 this.msg = msg;        setChanged();        notifyObservers("主题更新消息:"+this.msg);        clearChanged();         }}
package observer.jdk;import java.util.Observable;import java.util.Observer;/** * 观察者 * @author 发挥哥 * */public class MyObserver implements Observer {    /**     * 通过该方法将观察者自己注册到主题     * @param observable     */    public void registerToSubject(Observable observable) {        observable.addObserver(this);    }    @Override    public void update(Observable o, Object arg) {        System.out.println(this.getClass().getName()+"收到主题"+o.getClass().getName()+"更新消息:"+arg);    }}

编写测试方法:

package observer.jdk;public class MyTest {    public static void main(String[] args) {        //创建主题1、主题2        MySubject subject1=new MySubject();        OtherSubject subject2=new OtherSubject();        //创建观察者        MyObserver observer=new MyObserver();        //将观察者注册到主题1、主题2        observer.registerToSubject(subject1);        observer.registerToSubject(subject2);        //主题1、主题2分别更新状态        subject1.editMsg("主题一更新");        subject2.editMsg("主题二更新");    }}

测试结果如下:

observer.jdk.MyObserver收到主题observer.jdk.MySubject更新消息:主题更新消息:主题一更新

observer.jdk.MyObserver收到主题observer.jdk.OtherSubject更新消息:主题更新消息:主题二更新

比较好的观察者模式应用是微信公众号,公众号就是我们的主题,粉丝就是观察者。功能如下:

  • 1、公众号就是主题,业务就是推送新消息;
  • 2、观察者订阅主题,有新的消息自动送来;
  • 3、当不想要此主题消息时,取消订阅即可;

总结:

观察者模式的实现方式是在观察者调用主题的addObserver方法将自己添加到主题持有的观察者列表里,主题在需要的时候调用notifyObservers遍历观察者列表,并分别调用观察者的update方法。

打个比方,主题就是婚介所,多个观察者就是多个未婚大龄男青年,男青年注册会员之后将自己的联系方式交给婚介所,婚介所在合适的时候(比如来了适龄女青年),就会挨个给注册的男青年打电话通知。

转载于:https://www.cnblogs.com/kibana/p/8808388.html

你可能感兴趣的文章
node 知识点
查看>>
mybatis获取当前插入记录的id
查看>>
如何使用Terminalizer用于记录您的Linux终端会话并生成动画gif图像
查看>>
Spring3 MVC Hello World(3)使用JSON进行前后台数据交互
查看>>
WSDL实例解析
查看>>
用netbeans开发Swing程序,添加自定义控件
查看>>
LINUX Daemon程序设计
查看>>
solrcore.properties定义server是否是master
查看>>
什么是Node.js
查看>>
高通编译
查看>>
MySQL multiple instances on Ubuntu
查看>>
git常用命令整理
查看>>
第四章 数据抽象 ----《C++编程思想》
查看>>
【JSP报错】—— org.apache.jasper.JasperException: Unable to compile class for JSP
查看>>
ThreadLocal 类用法讲解
查看>>
git 获取kbengine 指定tag代码
查看>>
二字节转包长度
查看>>
java对象--特点
查看>>
Cobar使用文档(可用作MySQL大型集群解决方案)
查看>>
新浪微博新兵训练营系列课程——平台RPC框架介绍
查看>>