观察者模式可以说是Java jdk中使用率最高的一个模式了.而且jdk也自带实现了观察者模式,可见这个模式的重要性.
java.util下的public interface Observer
一个可在观察者要得到 observable 对象更改通知时可实现Observer接口的类。
方法摘要 |
void |
update(Observable o, Object arg) 只要改变了 observable 对象就调用此方法。 |
java.util.Observable 类
public class Observable extends Object此类表示模型视图范例中的 observable 对象,或者说“数据”。可将其子类化,表示应用程序想要观察的对象。 一个 observable 对象可以有一个或多个观察者。观察者可以是实现了 Observer 接口的任意对象。一个 observable 实例改变后,调用 Observable 的 notifyObservers 方法的应用程序会通过调用观察者的 update 方法来通知观察者该实例发生了改变。 未指定发送通知的顺序。Observable 类中所提供的默认实现将按照其注册的重要性顺序来通知 Observers,但是子类可能改变此顺序,从而使用非固定顺序在单独的线程上发送通知,或者也可能保证其子类遵从其所选择的顺序。 注意,此通知机制与线程无关,并且与 Object 类的 wait 和 notify 机制完全独立。 新创建一个 observable 对象时,其观察者集是空的。当且仅当 equals 方法为两个观察者返回 true 时,才认为它们是相同的。
构造方法摘要 |
Observable() 构造一个带有零个观察者的 Observable。 |
方法摘要 |
void |
addObserver(Observer o) 如果观察者与集合中已有的观察者不同,则向对象的观察者集中添加此观察者。 |
protected void |
clearChanged() 指示对象不再改变,或者它已对其所有的观察者通知了最近的改变,所以hasChanged方法将返回false。 |
int |
countObservers() 返回Observable对象的观察者数目。 |
void |
deleteObserver(Observer o) 从对象的观察者集合中删除某个观察者。 |
void |
deleteObservers() 清除观察者列表,使此对象不再有任何观察者。 |
boolean |
hasChanged() 测试对象是否改变。 |
void |
notifyObservers() 如果hasChanged方法指示对象已改变,则通知其所有观察者,并调用clearChanged方法来指示此对象不再改变。 |
void |
notifyObservers(Object arg) 如果hasChanged方法指示对象已改变,则通知其所有观察者,并调用clearChanged方法来指示此对象不再改变。 |
protected void |
setChanged() 标记此Observable对象为已改变的对象;现在hasChanged方法将返回true。 |
样例:
是这样的,有一个酒店价格更新的业务逻辑.每当酒店总部调整价格的时候,各个下属酒店的价格将发生变化. 我们在这里,将房间分为了normal,advanced,top三种.每种的价格都是由酒店总部调整. 首先运用观察者模式,写出核心类,在这里我得理解为核心类,这个核心类将会把最新的一些数据自动发生给各个下属酒店.
下面这个是观察者模式的核心-----被观察者.
01 | package org.pattern.observer.jdk; |
03 | import java.util.Observable; |
05 | public class ObserverCore extends Observable { |
07 | // 注意,我们继承了Observable,有很多方法供我们使用. |
08 | private double normal; |
09 | private double middle; |
13 | public void inputPrice( double normal, double middle, double top) { |
17 | this .sureToSendPrice(); |
21 | public void sureToSendPrice() { |
22 | this .setChanged(); //改变状态,change后卫true,开启发送必须先setChange. |
23 | notifyObservers(); //通知观察者 |
26 | public double getNormal() { |
30 | public double getMiddle() { |
34 | public double getTop() { |
下面将是两个观察者.观察者必须实现Ovserver接口,并实现其update方法.判断后进行获取值的操作.
01 | package org.pattern.observer.jdk; |
03 | import java.util.Observable; |
04 | import java.util.Observer; |
06 | public class HotelA implements Observer { |
10 | public HotelA(Observable ob) { |
16 | public void update(Observable o, Object arg) { |
17 | if (o instanceof ObserverCore){ |
18 | ObserverCore observerCore=(ObserverCore) o; |
19 | this .show(observerCore.getNormal(),observerCore.getMiddle(),observerCore.getTop()); |
23 | public void show( double normal, double middle, double top){ |
24 | System.out.println( "Anormal:" +normal); |
25 | System.out.println( "Amiddle:" +middle); |
26 | System.out.println( "Atop:" +top); |
01 | package org.pattern.observer.jdk; |
03 | import java.util.Observable; |
04 | import java.util.Observer; |
06 | public class HotelB implements Observer{ |
09 | public HotelB(Observable ob){ |
15 | public void update(Observable o, Object arg) { |
16 | if (o instanceof ObserverCore){ |
17 | ObserverCore observerCore=(ObserverCore) o; |
18 | this .show(observerCore.getNormal(),observerCore.getMiddle(),observerCore.getTop()); |
22 | public void show( double normal, double middle, double top){ |
23 | System.out.println( "Bnormal:" +normal); |
24 | System.out.println( "Bmiddle:" +middle); |
25 | System.out.println( "Btop:" +top); |
01 | package org.pattern.observer.jdk; |
05 | public static void main(String[] args) { |
06 | ObserverCore core= new ObserverCore(); |
08 | HotelA a= new HotelA(core); |
09 | HotelB b= new HotelB(core); |
11 | core.inputPrice( 1 , 2 , 3 ); |
12 | core.inputPrice( 11 , 22 , 33 ); |
13 | core.inputPrice( 111 , 222 , 333 ); |
觉得没啥意思,直接代码也就看懂了.
关于通知的顺序
值得注意的Observable 类中所提供的默认实现将按照其注册的顺序来通知 Observers.但是子类可能改变此顺序,从而使用非固定顺序在单独的线程上发送通知.
总之,绝对不要在观察者模式中试图去依赖次序.
其实我在这里想了会,感觉使用通知者模式,应用场景应该是多个被观察者(方便理解,可以认为这里的被观察者模式是webservice的接收数据的接口)之间并无关联的.执行的通知顺序并不重要,或者说可以不在意.
不好的地方
写到这里可以注意到,java自带的观察者模式是一个类而不是一个接口.那么这样就意味着要继承.而我们的设计原则是,多用组合,少用继承.
那么最好的方式就是去自己写一套观察着模式.
|