1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > OpenJDK源码研究笔记(六)--观察者模式工具类(Observer和Observable)和应用示例

OpenJDK源码研究笔记(六)--观察者模式工具类(Observer和Observable)和应用示例

时间:2021-11-01 10:40:27

相关推荐

OpenJDK源码研究笔记(六)--观察者模式工具类(Observer和Observable)和应用示例

独角兽企业重金招聘Python工程师标准>>>

本文主要讲解OpenJDK观察者模式的2个工具类,java.util.Observer观察者接口,java.util.Observable被观察者基类。

然后,给出了一个常见的观察者应用示例。

Observer观察者接口

/*** 一个类可以实现Observer接口,当它想要得到“被观察者”对象变化通知的时候*/public interface Observer {/*** 当被观察的对象发生变化时,这个方法被调用。一个应用调用Observable对象的notifyObservers方法,去通知所有的观察者, Observable对象发生了变化。* @param o被观察的对象.* @param arg 传递给notifyObservers方法的参数.*/void update(Observable o, Object arg);}

Observable被观察者基类

这个类代表一个可以观察的对象,或数据(在模型-视图范式中)。

它能够被继承去代表一个应用想要观察的对象。

一个observable对象可以有一个或多个观察者。

一个观察者可以是一个实现了Observer接口的对象。

当一个observable实例发生了变化,一个应用可以调用Observable的notifyObservers方法,去通知

它的观察者所发生的变化,通过调用观察者的update方法。

通知被传递的顺序是没有指定的。

在Observable类中的默认实现是,按注册顺序通知Observers。

但是子类可以改变这种顺序,使用没有保证的顺序,在分开的线程中传递通知,或者确保他们的子类遵循他们所选择的这个顺序。

注意:这个通知机制和线程没有任何关系,与Object对象的wait和notify机制没有任何关系。

当一个observable被新创建的时候,它的observer集合是空的。

两个observer被认为是同一个,当且仅当他们的equals方法比较返回true的时候。

public class Observable {//该对象是否已经发生了变化,默认为falseprivate boolean changed = false;//Vector是线程安全的,ArrayList是非线程安全的private Vector obs;//构造一个没有观察者的Observable对象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) {//我们不想要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对象已经发生了变化protected synchronized void setChanged() {changed = true;}//表明这个对象已经不再变化,或者说明已经通知到所有的观察者最近的一次变化。protected synchronized void clearChanged() {changed = false;}//测试该对象是否已经发生了变化。当且仅当setChanged方法比clearChanged方法调用的次数更多的时候,返回true。public synchronized boolean hasChanged() {return changed;}// 返回Observable对象的观察者的数量.public synchronized int countObservers() {return obs.size();}}

代码示例

书,被观察者(或者称之为订阅主题)

import java.util.Observable;//书,被观察者(或者称之为订阅主题)public class Book extends Observable {// 书的IDprivate Integer id;// 书名private String name;// 当前价格private Double price;// 当书的价格修改时,调用该方法public void modifyPrice(Double newPrice) {ChangeStatus status = null;// 差值大于0.01,就认为价格放生了变化if (Math.abs(newPrice - price) >= 0.01) {setChanged();status = new ChangeStatus();status.setId(id);status.setName(name);status.setOldPrice(price);status.setNewPrice(newPrice);}// 通知客户书已经降价notifyObservers(status);}public String getName() {return name;}public void setName(String name) {this.name = name;}public Double getPrice() {return price;}public void setPrice(Double price) {this.price = price;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}}

观察者:用户的邮箱

import java.util.Observable;import java.util.Observer;/*** 观察者:用户的邮箱*/public class BuyerEmail implements Observer {// 该方法会被“被观察者的父类”即Observable调用public void update(Observable o, Object arg) {// 这里做具体的发电子邮件的程序if (arg instanceof ChangeStatus) {NotifyUtils.sendEmail((ChangeStatus) arg);}}}

观察者:用户的手机

import java.util.Observable;import java.util.Observer;/*** 观察者:用户的手机*/public class BuyerMobile implements Observer {// 该方法会被“被观察者的父类”即Observable调用public void update(Observable o, Object arg) {// 这里做具体的发电子邮件的程序if(arg instanceof ChangeStatus){NotifyUtils.sendSMS((ChangeStatus)arg);}}}

一本书的信息变化的实体类

public class ChangeStatus {//书的IDprivate Integer id;//书名private String name;//过去的价格private Double oldPrice;//最新的价格private Double newPrice;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public Double getOldPrice() {return oldPrice;}public void setOldPrice(Double oldPrice) {this.oldPrice = oldPrice;}public Double getNewPrice() {return newPrice;}public void setNewPrice(Double newPrice) {this.newPrice = newPrice;}public String getName() {return name;}public void setName(String name) {this.name = name;}}

发送通知的工具类

public class NotifyUtils {// 发送邮件通知用户public static void sendEmail(ChangeStatus status) {print(status);}// 发送短信通知用户public static void sendSMS(ChangeStatus status) {print(status);}// 一种只是用来作为“演示”的发送信息的方法private static void print(ChangeStatus status) {println("*******************************************************");String messageContent = messageContent(status);println(messageContent);println("********************************************************");}private static String messageContent(ChangeStatus status) {// 一般,降价才会通知,这里只当是降价了String str = "尊敬的用户,您好!\n";str += "您收藏的图书《" + status.getName() + "》降价了。\n";str += "过去的价格是:" + status.getOldPrice() + "\n";str += "现在的价格是:" + status.getNewPrice() + "\n";str += "您可以通过以下链接 /FansUnion 进行购买。";return str;}private static void println(Object content) {System.out.println(content);}}

程序入口

public class ObserverPatternTest {/*** 观察者模式-用法示例*/public static void main(String[] args) {Book book = new Book();book.setName("中国象棋程序的设计与实现");book.setPrice(45.0);// 下面的观察者在实际应用中可以从数据库或文件中读取BuyerEmail email = new BuyerEmail();BuyerMobile mobile = new BuyerMobile();// 增加观察者,在实际应用中就是哪些人对该书作了关注book.addObserver(email);book.addObserver(mobile);book.modifyPrice(34.00);}}

输出结果

*******************************************************

尊敬的用户,您好!

您收藏的图书《中国象棋程序的设计与实现》降价了。

过去的价格是:45.0

现在的价格是:34.0

您可以通过以下链接 /FansUnion 进行购买。

********************************************************

*******************************************************

尊敬的用户,您好!

您收藏的图书《中国象棋程序的设计与实现》降价了。

过去的价格是:45.0

现在的价格是:34.0

您可以通过以下链接 /FansUnion 进行购买。

********************************************************

参考资料:OpenJDK7源码

原文参见:/articles/2936

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。