Java中的观察者模式
让一个类能够被观察,则该类需要继承java.util.Observable类。
要让一个类成为观察者,则该类需要实现java.util.Observable接口。
让观察者和被观察者建立联系通过Observable的addObserver(Object obj)方法。
让被观察者通知观察者,通过Observable类中的setChanged()和notifyObservers(Object obj)方法。
下面的例子定义了一个售房中心类和一个卖家类。售房中心为被观察者,买房者为观察者。售房中心房价发生变化,则将相应的信息通知买房者。
代码如下:
import java.util.*; class HouseSellCenter extends Observable { public String name; public float price; public HouseSellCenter(String name, float price) { this.name = name; this.price = price; } public void changePrice(float price) { this.price = price; super.setChanged(); super.notifyObservers(price); } public String toString() { return "name:" + this.name + " price:" +this.price; } } class Buyer implements Observer { public String name; public Buyer(String name) { this.name = name; } public void update(Observable o, Object arg) { HouseSellCenter hsc = (HouseSellCenter)o; System.out.println(this.name+"观察到:"+hsc.name+"房价变为:" + arg + "万"); } } class Hello { public static void main(String[] args) { HouseSellCenter hsc = new HouseSellCenter("金悦城",1.3f); Buyer buyer1 = new Buyer("金旭地产"); Buyer buyer2 = new Buyer("龙城中介"); Buyer buyer3 = new Buyer("祥龙置业"); hsc.addObserver(buyer1); hsc.addObserver(buyer2); hsc.addObserver(buyer3); System.out.println("============"); hsc.changePrice(1.5f); System.out.println("============"); sleep(3000); System.out.println("============"); hsc.changePrice(1.2f); System.out.println("============"); } public static void sleep(int timeSpan) { try { Thread.sleep(timeSpan); } catch (Exception e) { System.out.println(e); } } }
输出结果:
============ 祥龙置业观察到:金悦城房价变为:1.5万 龙城中介观察到:金悦城房价变为:1.5万 金旭地产观察到:金悦城房价变为:1.5万 ============ ============ 祥龙置业观察到:金悦城房价变为:1.2万 龙城中介观察到:金悦城房价变为:1.2万 金旭地产观察到:金悦城房价变为:1.2万 ============
上面的代码是利用了Java对观察者模式的支持。下面用另一个例子说明观察者模式运行规则。
Observerable接口(定义被观察者的规范):
public interface Observerable { void addObserver(ObserverBehavior newObserver); void removeObserver(ObserverBehavior observerToBeRemoved); void notifyAllObservers(); }
ObserverBehavior接口(定义观察者的规范):
public interface ObserverBehavior { void update(float temperature, float humidity, float pressure); }
WeatherData类实现Observerable接口,其是真实的被观察者类:
import java.util.List; import java.util.ArrayList; public class WeatherData implements Observerable { private List<ObserverBehavior> observerList; private float temperature; private float humidity; private float pressure; public WeatherData() { this.observerList = new ArrayList<ObserverBehavior>(); } @Override public void addObserver(ObserverBehavior newObserver) { // TODO Auto-generated method stub this.observerList.add(newObserver); } @Override public void notifyAllObservers() { // TODO Auto-generated method stub for(ObserverBehavior observer : this.observerList) { observer.update(this.temperature, this.humidity, this.pressure); } } @Override public void removeObserver(ObserverBehavior observerToBeRemoved) { // TODO Auto-generated method stub this.observerList.remove(observerToBeRemoved); } public void weatherChanged(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; this.notifyAllObservers(); } }
MobileDevices实现ObserverBehavior类(真正的观察者):
public class MobileDevices implements ObserverBehavior { private String name; public MobileDevices(String name) { this.name = name; } @Override public void update(float temperature, float humidity, float pressure) { // TODO Auto-generated method stub System.out.println(this.name + "观察到当前 --> 温度:" + temperature + " 湿度:" + humidity + " 气压:" + pressure); } @Override public boolean equals(Object obj) { if(this == obj) return true; if(!(obj instanceof MobileDevices)) return false; MobileDevices otherOne = (MobileDevices)obj; if(this.name.equals(otherOne.name)) return true; else return false; } }
WhiteBoard实现了ObserverBehavior类(另一个真正的观察者):
public class WhiteBoard implements ObserverBehavior { private String name; public WhiteBoard(String name) { this.name = name; } @Override public void update(float temperature, float humidity, float pressure) { // TODO Auto-generated method stub System.out.println(this.name + "观察到当前 --> 温度:" + temperature + " 湿度:" + humidity + " 气压:" + pressure); } }
主方法测试:
public class Tester { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub WeatherData subject = new WeatherData(); WhiteBoard wb = new WhiteBoard("中央广场白板"); MobileDevices iphone = new MobileDevices("iphone手机"); MobileDevices android = new MobileDevices("安卓手机"); subject.addObserver(wb); subject.addObserver(iphone); subject.weatherChanged(12, 23, 33); subject.removeObserver(new MobileDevices("iphone手机")); subject.addObserver(android); subject.weatherChanged(22, 43, 25); } }
输出结果:
中央广场白板观察到当前 --> 温度:12.0 湿度:23.0 气压:33.0
iphone手机观察到当前 --> 温度:12.0 湿度:23.0 气压:33.0
中央广场白板观察到当前 --> 温度:22.0 湿度:43.0 气压:25.0
安卓手机观察到当前 --> 温度:22.0 湿度:43.0 气压:25.0
总结:
被观察者应该具备以下功能:
1) 能增加一个观察者 addObserver
2)能移除一个观察者 removeObserver
3)在数据改变的时候能将相应的信息通知给被观察者 notifyAllObservers
观察者应具备以下功能:
1) update方法用于观察者接收被观察者的推送信息