扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
今天就跟大家聊聊有关JAVA的观察者模式的作用是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
创新互联公司作为成都网站建设公司,专注网站建设、网站设计,有关成都定制网站方案、改版、费用等问题,行业涉及社区文化墙等多个领域,已为上千家企业服务,得到了客户的尊重与认可。
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。观察者模式是Java非常重要的一个设计模式。
观察者模式所涉及的角色有:
● 抽象主题(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。
● 具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。
● 抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。
● 具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。
抽象主题(subject)角色:
import java.util.ArrayList; import java.util.List; public abstract class Subject { private Listlist = new ArrayList<>(); public void register(MyObserver myObserver){ if (!list.contains(myObserver)){ list.add(myObserver); } } public void remove(MyObserver myObserver){ if (list.contains(myObserver)){ list.remove(myObserver); } } public void notifyObserver(){ for (MyObserver myObserver : list) { myObserver.update(); } } }
抽象观察者角色:
public interface MyObserver { void update(); }
具体主题角色:
public class Repoter extends Subject { private String msg; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; if (change()) { notifyObserver(); } } public Boolean change() { if (msg.equals(getMsg())) { return true; } else { return false; } } }
第一个具体观察者对象:
public class PeopleDaily implements MyObserver { private Subject subject; public PeopleDaily(Subject subject) { this.subject = subject; subject.register(this); } @Override public void update() { System.out.println("人民日报发布最新报道:" + ((Repoter) subject).getMsg()); } public void remove() { subject.remove(this); } }
第二个具体观察者对象:
public class NewsFeeds implements MyObserver { private Subject subject; public NewsFeeds(Subject subject) { this.subject = subject; subject.register(this); } @Override public void update() { System.out.println("新闻联播发布最新报道:" + ((Repoter) subject).getMsg()); } public void remove() { subject.remove(this); } }
第三个具体观察者对象:
public class XinHuaNewsAgency implements MyObserver { private Subject subject; public XinHuaNewsAgency(Subject subject) { this.subject = subject; subject.register(this); } @Override public void update() { System.out.println("新华社发布最新报道:" + ((Repoter) subject).getMsg()); } public void remove() { subject.remove(this); } }
测试:
public class TestDemo { @Test public void demo(){ Repoter repoter = new Repoter(); NewsFeeds newsFeeds = new NewsFeeds(repoter); XinHuaNewsAgency xinHuaNewsAgency = new XinHuaNewsAgency(repoter); PeopleDaily peopleDaily = new PeopleDaily(repoter); repoter.setMsg("为实现中华民族伟大复兴而奋斗!!!"); } }
结果:
新闻联播发布最新报道:为实现中华民族伟大复兴而奋斗!!! 新华社发布最新报道:为实现中华民族伟大复兴而奋斗!!! 人民日报发布最新报道:为实现中华民族伟大复兴而奋斗!!! Process finished with exit code 0
删除一个观察者再试:
public class TestDemo { @Test public void demo(){ Repoter repoter = new Repoter(); NewsFeeds newsFeeds = new NewsFeeds(repoter); XinHuaNewsAgency xinHuaNewsAgency = new XinHuaNewsAgency(repoter); PeopleDaily peopleDaily = new PeopleDaily(repoter); repoter.setMsg("为实现中华民族伟大复兴而奋斗!!!"); repoter.remove(xinHuaNewsAgency); System.out.println("————————————————————————————————————————————————"); repoter.setMsg("华为发布最新旗舰机Mate30系列型号手机"); } }
结果:
新闻联播发布最新报道:为实现中华民族伟大复兴而奋斗!!! 新华社发布最新报道:为实现中华民族伟大复兴而奋斗!!! 人民日报发布最新报道:为实现中华民族伟大复兴而奋斗!!! ———————————————————————————————————————————————— 新闻联播发布最新报道:华为发布最新旗舰机Mate30系列型号手机 人民日报发布最新报道:华为发布最新旗舰机Mate30系列型号手机 Process finished with exit code 0
对于观察者模式,JDK已经为我们提供了对应的接口和类。
JDK源代码:
package java.util;
/**
*
* 当一个类想要被告知可观察对象的变化时,它可以实现 Observer 接口。
* @author Chris Warth
* @see java.util.Observable
* @since JDK1.0
*/
public interface Observer {
/**
*
* 每当观察对象发生变化时,都会调用此方法。应用程序调用 Observable 对象的 notifyObservers 方法,以便让所有对
* 象的观察者收到更改通知。
* @param o the observable object.
* @param arg an argument passed to the notifyObservers
* method.
*/
void update(Observable o, Object arg);
}
Observer是一个接口,只是一个方法update用于接收通知者的通知并做出相应,具体的逻辑肯定是需要开发者自己实现的了。
被观察者,JDK的源码如下:
package java.util; /** * * 此类表示可观察对象,或模型 - 视图范例中的“数据”。它可以被子类化以表示应用程序想要观察的对象。 * 可观察对象可以有一个或多个观察者。观察者可以是实现接口 Observer 的任何对象。 * 在可观察的实例发生更改后,调用 Observable 的 notifyObservers 方法,应用程序会通过调用 update 来通知所有观察 * 者的更改。 * 未指定通知的递送顺序。 Observable类中提供的默认实现将按照它们注册的顺序通知Observers,但是子类可能会更改此顺 * 序,使用不保证顺序,在单独的线程上发送通知,或者可以保证它们的子类遵循此顺序,因为它们选择。 * 请注意,此通知机制与线程无关,并且与类 Object 的 wait 和 notify 机制完全分开。 * 当新创建可观察对象时,其观察者集合为空。当且仅当 equals 方法为它们返回true时,才认为两个观察者是相同的。 * @author Chris Warth * @see java.util.Observable#notifyObservers() * @see java.util.Observable#notifyObservers(java.lang.Object) * @see java.util.Observer * @see java.util.Observer#update(java.util.Observable, java.lang.Object) * @since JDK1.0 */ public class Observable { private boolean changed = false; private Vectorobs; //构造方法 public Observable() { obs = new Vector<>(); } /** * 将观察者添加到此对象的观察者集中,前提是它与集合中已有的某个观察者不同。未指定将通知发送给多个观察者的顺序。 * @param o an observer to be added. * @throws NullPointerException if the parameter o is null. */ public synchronized void addObserver(Observer o) { if (o == null) throw new NullPointerException(); if (!obs.contains(o)) { obs.addElement(o); } } /** * * 从该对象的观察者集中删除观察者。将 null 传递给此方法将不起作用。 * @param o the observer to be deleted. */ public synchronized void deleteObserver(Observer o) { obs.removeElement(o); } /** * * 如果此对象已更改,如 hasChanged 方法所示,则通知其所有观察者,然后调用 clearChanged 方法以指示此对象不再 * 更改。 * 每个观察者都使用两个参数调用 update 方法:observable对象和 null 。换句话说,此方法等效于: * notifyObservers(null) * @see java.util.Observable#clearChanged() * @see java.util.Observable#hasChanged() * @see java.util.Observer#update(java.util.Observable, java.lang.Object) */ public void notifyObservers() { notifyObservers(null); } /** * * 如果此对象已更改,如 hasChanged 方法所示,则通知其所有观察者,然后调用 clearChanged 方法以指示此对象不再 * 更改。 * 每个观察者都使用两个参数调用 update 方法:observable对象和 arg 参数。 * @param arg any object. * @see java.util.Observable#clearChanged() * @see java.util.Observable#hasChanged() * @see java.util.Observer#update(java.util.Observable, java.lang.Object) */ public void notifyObservers(Object arg) { /* * * 临时数组缓冲区,用作当前Observers状态的快照。 */ Object[] arrLocal; synchronized (this) { /* * 我们不希望Observer在拥有自己的Monitor时进行任意代码的回调。我们从Vector中提取每个Observable并存 * 储Observer状态的代码需要同步,但是通知观察者不会(不应该)。这里任何潜在竞争条件的最坏结果是: * 1)新添加的观察者将错过正在进行的通知 * 2)最近未注册的观察者将被错误地通知 */ 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(); } /** * * 将此 Observable 对象标记为已更改; hasChanged 方法现在将返回 true 。 */ protected synchronized void setChanged() { changed = true; } /** * * 表示此对象已不再更改,或者已向其所有观察者通知其最近的更改,因此 hasChanged 方法现在将返回 false 。 * 此方法由 notifyObservers 方法自动调用。 * @see java.util.Observable#notifyObservers() * @see java.util.Observable#notifyObservers(java.lang.Object) */ protected synchronized void clearChanged() { changed = false; } /** * * 测试此对象是否已更改。 * @return true
if and only if thesetChanged
* method has been called more recently than the *clearChanged
method on this object; *false
otherwise. * @see java.util.Observable#clearChanged() * @see java.util.Observable#setChanged() */ public synchronized boolean hasChanged() { return changed; } /** * * 返回此 Observable 对象的观察者数。 * @return the number of observers of this object. */ public synchronized int countObservers() { return obs.size(); } }
Java源码使用Vector,Vector相比于ArrayList来说,它是线程安全的。在添加和删除观察者时对两个方法使用了synchronized关键字,这都是在为多线程考虑。
观察者:实现观察者接口(java.util.Observer),然后调用任何Observable对象的addObserver()方法,注销观察者时,就调用deleteObserver()方法即可。
第一个观察者对象:
public class XinhuaNewsAgency implements Observer { //被观察者对象 private Observable observable; public XinhuaNewsAgency(Observable observable) { this.observable = observable; //将观察者对象加入到观察者集合中 observable.addObserver(this); } @Override public void update(Observable o, Object arg) { if(o instanceof Repoter){ System.out.println("新华社发布最新报道:" + ((Repoter) o).getMsg()); } } public void remove(){ //删除观察者 observable.deleteObserver(this); } }
第二个观察者对象:
public class PeopleDaily implements Observer { //被观察者对象 private Observable observable; public PeopleDaily(Observable observable) { this.observable = observable; //将观察者对象加入到观察者集合中 observable.addObserver(this); } @Override public void update(Observable o, Object arg) { if (o instanceof Repoter){ System.out.println("人民日报发布最新报道:" + ((Repoter) o).getMsg()); } } public void remove(){ //删除观察者 observable.deleteObserver(this); } }
第三个观察者对象:
public class NewsFeeds implements Observer { //被观察对象 private Observable observable; public NewsFeeds(Observable observable) { this.observable = observable; //将观察者对象加入到观察者集合中 observable.addObserver(this); } @Override public void update(Observable o, Object arg) { if (o instanceof Repoter){ System.out.println("新闻联播发布最新报道:" + ((Repoter) o).getMsg()); } } public void remove(){ //删除观察者 observable.deleteObserver(this); } }
被观察者:继承java.util.Observable类,调用setChanged()方法,标记状态改变。然后调用nofityObservers()方法或者notifyobservers(Object arg) 方法。
public class Repoter extends Observable { private String msg; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; this.setChanged(); this.notifyObservers(msg); } }
测试:
public class TestDemo { @Test public void demo(){ Repoter repoter = new Repoter(); NewsFeeds newsFeeds = new NewsFeeds(repoter); PeopleDaily peopleDaily = new PeopleDaily(repoter); XinhuaNewsAgency xinhuaNewsAgency = new XinhuaNewsAgency(repoter); repoter.setMsg("为实现中华民族伟大复兴而奋斗!!!"); } }
结果:
新华社发布最新报道:为实现中华民族伟大复兴而奋斗!!! 人民日报发布最新报道:为实现中华民族伟大复兴而奋斗!!! 新闻联播发布最新报道:为实现中华民族伟大复兴而奋斗!!! Process finished with exit code 0
结果发现顺序和注册的顺序并不一致。将新闻联播注销,在运行:
public class TestDemo { @Test public void demo(){ Repoter repoter = new Repoter(); NewsFeeds newsFeeds = new NewsFeeds(repoter); PeopleDaily peopleDaily = new PeopleDaily(repoter); XinhuaNewsAgency xinhuaNewsAgency = new XinhuaNewsAgency(repoter); repoter.setMsg("为实现中华民族伟大复兴而奋斗!!!"); newsFeeds.remove(); System.out.println("————————————————————————————————————————————————"); repoter.setMsg("华为发布最新旗舰机Mate30系列型号手机"); } }
结果:
新华社发布最新报道:为实现中华民族伟大复兴而奋斗!!! 人民日报发布最新报道:为实现中华民族伟大复兴而奋斗!!! 新闻联播发布最新报道:为实现中华民族伟大复兴而奋斗!!! ———————————————————————————————————————————————— 新华社发布最新报道:华为发布最新旗舰机Mate30系列型号手机 人民日报发布最新报道:华为发布最新旗舰机Mate30系列型号手机 Process finished with exit code 0
劣势:
Observable是一个类,而不是一个接口,导致Observable类的扩展性不高,不如自己实现的观察者模式灵活。
Observable将某些方法保护了起来(setChanged()和clearChanged()为protected),这意味着除非继承自Observable,否则将有关键的方法不能调用。导致无法通过组合的方式使其它类获得Observable类的功能。
看完上述内容,你们对JAVA的观察者模式的作用是什么有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注创新互联行业资讯频道,感谢大家的支持。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流