定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖都会收到通知并自动更新
2.设计原则
a.封装变化
b.多用组合少用继承
c.针对接口编程,不针对实现编程
d.为交互对象之间的松耦合设计而努力
3.代码示例:一个气象站与多个公布板
思路:气象站可以监测当前天气的种种数据,建立一个WeatherData对象,该对象可以注册,移除观察者,并且当从气象站获取数据(使用模拟数据)后,
它会执行相应的方法通知各个观察者,此处的观察者即为布告板
根据针对接口编程的原则,可以建立一个Subject接口,它包含注册,删除,通知观察者三个方法,让weatherData对象去实现它
又因为,布告板即为观察者,为实现解耦,我们应该提供一个统一的通知方法给WeatherData对象,当需要通知观察者时,WeatherData对象不需要关心观察者
都有谁,而是调用统一的方法去通知他们,因此,观察者都应该具有update()方法以便WeatherData对象通知,这是它们的共性,因此单独抽取出来建立一个只含有
update()方法的接口,所有的观察者都因该实现该接口
整理好思路开始编码实现
/*
* 被观察者接口
*/
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObserver();
}/*
* 观察者接口
*/
public interface Observer {
public void update(float temp,float pressure,float humidity);
}/*
* 一个实现行为而已
*/
public interface DisplayElements {
public void display();
}/*
* 被观察者实现
*/
public class WeatherData implements Subject {
private float temp;
private float pressure;
private float humidity;
private ArrayList observers;
public WeatherData() {
observers = new ArrayList();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
if( i >= 0) {
observers.remove(i);
}
}
@Override
public void notifyObserver() {
for (int i = 0; i < observers.size(); i++) {
Observer o = (Observer) observers.get(i);
o.update(temp, pressure, humidity);
}
}
/**
* 模拟该对象从气象站获取当前天气资料
*/
public void getMeasurementData(float temp,float pressure,float humidity) {
this.temp = temp;
this.pressure = pressure;
this.humidity = humidity;
//一旦数据更新便通知观察者们
notifyObserver();
}
}/*
* 一个观察者的具体实现
*/
public class CurrCondition implements Observer,DisplayElements {
private float temp;
private float pressure;
private float humidity;
private WeatherData weatherData;
public CurrCondition(Subject weatherData) {
this.weatherData = (WeatherData) weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("当前温度为 " + this.temp);
}
@Override
public void update(float temp, float pressure, float humidity) {
this.temp = temp;
this.pressure = pressure;
this.humidity = humidity;
display();
}
}public class TeatApp {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrCondition currCondition = new CurrCondition(weatherData);
weatherData.getMeasurementData(1f, 3.3f,2.09f);
weatherData.getMeasurementData(100f, 3.3f,2.09f);
}
}总结:
观察者模式的核心同我们简单的接口调用一样,只是我们常用的接口调用的时候常用setXXXXX方法设置一个监听,当监听到的时候我们给设置了监听的一个对象一个回调方法,而观察者模式只是将多个监听对象放到了一个集合里,当变化时给所有的监听对象都回调一下。
4.使用Java提供的观察者实现观察者模式
Java.Util包下有一个observable类和一个observer接口,他们分别是让被观察者和观察者继承从而实现观察者模式。下面是一个很简单的代码。
/*
* 被观察者
*/
public class Person extends Observable {
private String name;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
//标记此 Observable 对象为已改变的对象;现在 hasChanged 方法将返回 true。
this.setChanged();
//如果 hasChanged 方法指示对象已改变,则通知其所有观察者,并调用 clearChanged 方法来指示此对象不再改变。
this.notifyObservers();
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
//标记此 Observable 对象为已改变的对象;现在 hasChanged 方法将返回 true。
this.setChanged();
//如果 hasChanged 方法指示对象已改变,则通知其所有观察者,并调用 clearChanged 方法来指示此对象不再改变。
this.notifyObservers();
}
}/*
* 观察者
*/
public class MyObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("对象发生了改变");
}
}public class TestApp {
public static void main(String[] args) {
//被观察者对象
Person p = new Person();
//注册观察者
p.addObserver(new MyObserver());
//使对象发生变化
p.setName("Jiaxx3");
p.setSex("woman");
}
}实际中我们可采用jdk所提供的工具,大大简化了开发,其原理和前半部分我们的实现是一样的。
原文:http://blog.51cto.com/12222886/2047429