观察者模式:有时又被称为发布(publish )-订阅(Subscribe)模式、模型-视图(View)模式、源-收听者(Listener)模式或从属者模式),是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。
现在用《headfirst设计模式》书上的例子理解一下
1.定义主题接口:所有的主题必须实现此接口,前两个方法需要传入一个观察者对象作为参数,实现注册和删除观察者。最后一个方法用来在主题状态改变时通知所有的观察者。
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
2.定义观察者接口:所有观察者必须实现此接口,实现update()方法,这里将观测值传入观察者中,当气象观测值改变时,主题会把这些状态值当作此方法的参数,传给观察者。实现display()方法将其按照自己的方式输出在控制台。
public interface Observer {
public void update(float temperature,float humidity,float pressure);
public void display();
}
3.具体主题:实现主题接口,并重写方法,添加自己的方法。
import java.util.ArrayList;
public class WeatherDate implements Subject {
//这里用ArrayList来记录观察者,将其在构造器中建立
private ArrayList observers;
//定义WeatherDate主题的相关内容变量
private float temperature;
private float humidity;
private float pressure;
public WeatherDate() {
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 notifyObservers() {
for(int i=0;i<observers.size();i++){
Observer observer=(Observer) observers.get(i);
observer.update(temperature, humidity, pressure);
}
}
//当得到新的观测值时调用通知方法
public void measurementsChanged(){
notifyObservers();
}
public void setMessurements(float temperature,float humidity,float pressure){
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
4.具体观察者
第一个具体观察者:实现观察者接口,重写方法。只输出展现温度和湿度
public class CurrentConditionDisplayOne implements Observer {
private float temperature;
private float humidity;
private Subject weatherDate;
public CurrentConditionDisplayOne(Subject weatherDate) {
this.weatherDate = weatherDate;
weatherDate.registerObserver(this);
}
@Override
public void display() {
System.out.println("Current condition One:"+temperature+"F degrees"+" "+humidity+"%humidity");
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
}
第二个具体观察者:实现观察者接口,重写方法。只输出展现压力和湿度。
public class CurrentConditionDisplayTwo implements Observer {
private float pressure;
private float humidity;
private Subject weatherDate;
public CurrentConditionDisplayTwo(Subject weatherDate) {
this.weatherDate = weatherDate;
weatherDate.registerObserver(this);
}
@Override
public void display() {
System.out.println("Current condition Two:"+pressure+"N"+" "+humidity+"%humidity");
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.pressure = pressure;
this.humidity = humidity;
display();
}
}
第三个对象,,,
测试类:
public class WeatherStation {
public static void main(String[] args) {
WeatherDate weatherDate=new WeatherDate();
CurrentConditionDisplayOne currentConditionDisplayOne=
new CurrentConditionDisplayOne(weatherDate);
CurrentConditionDisplayTwo currentConditionDisplayTwo=
new CurrentConditionDisplayTwo(weatherDate);
weatherDate.setMessurements(80, 65, 30.4f);
System.out.println("-------------");
weatherDate.removeObserver(currentConditionDisplayTwo);
weatherDate.setMessurements(70, 15, 25.3f);
}
}
控制台输出:
Current condition One:80.0F degrees 65.0%humidity
Current condition Two:30.4N 65.0%humidity
-------------
Current condition One:70.0F degrees 15.0%humidity
观察者模式,在对象之间定义一对多的依赖,这样一来当主题对象改变时,依赖它的所有观察者对象都会收到通知并自动更新。
观察者模式的应用场景:
1、 对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。
2、 对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。
观察者模式的优点:
1、 Subject和Observer之间是松偶合的,分别可以各自独立改变。
2、 Subject在发送广播通知的时候,无须指定具体的Observer,Observer可以自己决定是否要订阅Subject的通知。
3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
观察者模式的缺陷:
1、 松偶合导致代码关系不明显,有时可能难以理解。(废话)
2、 如果一个Subject被大量Observer订阅的话,在广播通知的时候可能会有效率问题。(毕竟只是简单的遍历)
引用链接:http://www.cnblogs.com/justinw/archive/2007/05/02/734522.html