博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java设计模式之观察者模式
阅读量:4030 次
发布时间:2019-05-24

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

观察者模式:

用报纸订阅的方式来说明:

1、报社的业务就是出版报纸

2、向某家报社订阅报纸,只要他们有新报纸出版,就会给你送来。只要你是他们的订户,就会一直收到报纸

3、当你不想再看报纸的时候,取消订阅,他们就不会再送来新报纸

4、只要报社还在运营,就会一直有人向他们订阅报纸或者取消订阅报纸

观察者模式的流程跟报纸订阅方式一致,即:观察者模式=出版者+订阅者,只是名称不一样,出版者改称为“主题”(Subject),订阅者改称为“观察者”(Observer)。

观察者定义:

观察者模式定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新。

主题接口(Subject):对象使用此接口注册为观察者,或者把自己从观察者中删除。

具体主题(ConcreteSubject):一个具体主题总是实现主题接口,除了注册*和撤销方法以外,具体主题还实现了notifyObserves()方法,此方法用于在状态改变时更新所有当前观察者。

观察者(Observer):为那些在目标发生改变时需获得通知的对象定义更新的接口

具体观察者(ConcreteObserver):具体观察者实现了观察者Observer接口,并注册具体主题,以便接收更新。

观察者模式提供了一种对象设计,让主题和观察者之间松耦合,当两个对象之间松耦合,它们依然可以交互,但是不太清楚彼此的细节,主题只知道观察者实现了Observer接口,不需要知道观察者的具体类是谁,做了些什么其他的细节。

观察者实例:

通过ConcreteObserver注册两个观察者ConcreteObserverA和ConcreteObserverB,一旦被观察者有更新,两个观察者会立刻收到更新通知。具体代码如下:

声明Subject主题接口,Subject.java:

public interface Subject {    void registerObserver(Observer observer);    void removeObserver(Observer observer);    void notifyObservers();}

声明ConcreteObserver具体主题,NetConcreteSubject.java:

public class NetConcreteSubject implements Subject {
private List
observers; private ObserverBean bean; public NetConcreteSubject() { observers = new ArrayList<>(); } @Override public void registerObserver(Observer observer) { observers.add(observer); } @Override public void removeObserver(Observer observer) { int pos = observers.indexOf(observer); if (pos > 0) { observers.remove(pos); } } @Override public void notifyObservers() { if (bean == null) return; for (int i = 0; i < observers.size(); i++) { Observer observer = observers.get(i); observer.update(bean); } } public void setStatusChanged(ObserverBean bean) { this.bean = bean; notifyObservers(); }}

声明观察者接口, Observer.java:

public interface Observer {    void update(Object obj);}

声明具体观察者类,ConcreteObserverA.java:

public class ConcreteObserverA implements Observer {
@Override public void update(Object obj) { if (obj instanceof ObserverBean) { ObserverBean bean = (ObserverBean) obj; System.out.print("ConcreteObserverA 网络类型:" + bean.netType + ",网络状态:" + bean.netStatus + "\n"); } }}

ConcreteObserverB.java:

public class ConcreteObserverB implements Observer {
@Override public void update(Object obj) { if (obj instanceof ObserverBean) { ObserverBean bean = (ObserverBean) obj; System.out.print("ConcreteObserverB 网络类型:" + bean.netType + ",网络状态:" + bean.netStatus + "\n"); } }}

调用过程:

public static void main(String[] args) {       //初始化主题(被观察者)       NetConcreteSubject subject = new NetConcreteSubject();       //初始化观察者A       ConcreteObserverA observerA = new ConcreteObserverA();       //初始化观察者B       ConcreteObserverB observerB = new ConcreteObserverB();       //注册观察者A       subject.registerObserver(observerA);       //注册观察者B       subject.registerObserver(observerB);       //通知所有观察者数据有更新       ObserverBean bean = new ObserverBean("wifi", "有网");       subject.setStatusChanged(bean);   }

运行结果:

ConcreteObserverA 网络类型:wifi,网络状态:有网ConcreteObserverB 网络类型:wifi,网络状态:有网

Java内置观察者:

Observable.java:

/** * Java学习交流QQ群:589809992 我们一起学Java! */public class Observable {
private boolean changed = false; private Vector
obs = new Vector(); public Observable() { } public synchronized void addObserver(Observer var1) { if(var1 == null) { throw new NullPointerException(); } else { if(!this.obs.contains(var1)) { this.obs.addElement(var1); } } } public synchronized void deleteObserver(Observer var1) { this.obs.removeElement(var1); } public void notifyObservers() { this.notifyObservers((Object)null); } public void notifyObservers(Object var1) { Object[] var2; synchronized(this) { if(!this.changed) { return; } var2 = this.obs.toArray(); this.clearChanged(); } for(int var3 = var2.length - 1; var3 >= 0; --var3) { ((Observer)var2[var3]).update(this, var1); } } public synchronized void deleteObservers() { this.obs.removeAllElements(); } protected synchronized void setChanged() { this.changed = true; } protected synchronized void clearChanged() { this.changed = false; } public synchronized boolean hasChanged() { return this.changed; } public synchronized int countObservers() { return this.obs.size(); }}

Observer.java:

public interface Observer {    void update(Observable var1, Object var2);}

上面的Observer和Observable类都位于java.util目录中,是JDK中已经写好的,那么我们可以直接拿来用了:

主题类NetSubject.java:

public class NetSubject extends Observable {
public void setNetChanged(ObserverBean bean){ setChanged(); notifyObservers(bean); }}

观察者SystemObserverA.java:

public class SystemObserverA implements Observer {
@Override public void update(Observable observable, Object o) { if (o instanceof ObserverBean && observable instanceof NetSubject) { ObserverBean bean = (ObserverBean) o; System.out.print("ConcreteObserverA 网络类型:" + bean.netType + ",网络状态:" + bean.netStatus + "\n"); } }}

观察者SystemObserverB.java:

/** * Java学习交流QQ群:589809992 我们一起学Java! */public class SystemObserverB implements Observer {
@Override public void update(Observable observable, Object o) { if (o instanceof ObserverBean && observable instanceof NetSubject) { ObserverBean bean = (ObserverBean) o; System.out.print("ConcreteObserverB 网络类型:" + bean.netType + ",网络状态:" + bean.netStatus + "\n"); } }}

执行程序:

//初始化主题(被观察者)   NetSubject subject = new NetSubject();   //初始化观察者A   SystemObserverA observerA = new SystemObserverA();   //初始化观察者B   SystemObserverB observerB = new SystemObserverB();   //注册观察者A   subject.addObserver(observerA);   //注册观察者B   subject.addObserver(observerB);   //通知观察者有更新   ObserverBean bean = new ObserverBean("4G流量", "有网");   subject.setNetChanged(bean);

运行结果:

ConcreteObserverB 网络类型:4G流量,网络状态:有网ConcreteObserverA 网络类型:4G流量,网络状态:有网

注意:

当使用JDK内置观察者模式时,当需要通知观察者更新数据时,首先需要调用setChanged()来改变状态,否则观察者不会收到任何更新通知。为什么会这样呢,来看下JDK中的源码就知道了:

private boolean changed = false; protected synchronized void setChanged() {        this.changed = true;    }  public void notifyObservers(Object var1) {        Object[] var2;        synchronized(this) {           //如果changed为false,将直接返回            if(!this.changed) {                return;            }            var2 = this.obs.toArray();            this.clearChanged();        }        for(int var3 = var2.length - 1; var3 >= 0; --var3) {            ((Observer)var2[var3]).update(this, var1);        }    }

通过setChanged()将changed设置为true,否则当调用notifyObservers(Object var1)将没有任何作用。

使用JDK内置观察者模式看似程序更简单了,但缺点也暴露出来了:

1、Observable是一个类,而不是一个接口,导致Observable类的扩展性不高,限制了它的使用和复用。
2、Observable将某些方法保护了起来(setChanged()和clearChanged()为protected),这意味着除非继承自Observable,否则将有关键的方法不能调用。导致无法通过组合的方式使其它类获得Observable类的功能

所以,如果JDK内置的观察者模式符合你的需求,那么可以尽情的使用内置的观察者模式,否则应该自己实现一套观察者模式。

转载地址:http://xvrbi.baihongyu.com/

你可能感兴趣的文章
事件委托(事件代理)
查看>>
函数防抖和函数节流
查看>>
vue中diff算法
查看>>
电商后台管理系统打包上线
查看>>
Netty物联网高并发系统第一季
查看>>
Elasticsearch在互联网应用中遇到的问题汇总
查看>>
Spring Cloud微服务架构在互联网中应用
查看>>
gradle+maven+springboot实战
查看>>
uWSGI使用详解
查看>>
如何在ubuntu上卸载Jenkins
查看>>
Oracle数据库导入导出,exp/imp expdp/impdp
查看>>
Android开发中对应的三种照片的尺寸
查看>>
注册DLL、OCX的方法
查看>>
Android Theme即样式 简介
查看>>
ArcEngine ICoommand和ITool 的区别
查看>>
MyEclipse常用快捷键(逐步更新)
查看>>
Jquery之显示/隐藏
查看>>
jQuery之滑动
查看>>
远程桌面无法复制粘贴
查看>>
Eclipse+adt+sdk配置Android开发环境
查看>>