观察者模式
观察者模式定义了一系列对象之间的一对多关系。
当一个对象改变状态其他依赖者都会收到通知。
一对多:
利用观察者模式,主题是具有状态的对象,并且可以控制状态。也就是说,有“一个”
具有状态的主题。另一方面,观察者使用这些状态,虽然这些状态并不属于它们。有
许多的观察者,依赖主题来告诉她们状态何时改变了。这就产生一个关系:“一个”主题对
“多个”观察者的关系。
松耦合:
改变主题或观察者其中一方,并不会影响另一方。
松耦合的设计之所以能让我们建立富有弹性的OO系统,能够应付变化,是因为对象之间的互相
依赖降低到了最低。
要点:
1、观察者模式定义了对象之间一对多的关系。
2、主题(也就是可观察者)用一个共同的接口来更新观察者
3、观察者和可观察者之间用松耦合方式结合(loosecoupling),可观察者不知道观察者的细节,只知道观察者实现了观察者接口。
4、使用此模式时,你可以从被观察者处推(push)或者拉(pull)数据(然而,推的方式被认为更“正确”)。
5、使用此模式时,不可以依赖特定的通知次序。
6、Swing大量使用观察者模式,许多GUI框架也是如此。
7、此模式也被应用在许多地方。例如:JavaBeans、RMI
8、Java有多种观察者模式的实现,包括了通用的java.util.Observable
要注意java.util.Observable实现上所带来的一些问题。如果有必要的话,可以实现自己的Observable,这并不难,Donot afraid
--------------------------------------------------
Swing使用观察者模式:
//观察者,实现接口
public class TestListener implements ActionListener{
public void actionPerformed(ActionEvent event)
{
//...
}
}
//被观察者
JButton btn = new JButton("test");
//相当于注册过程
btn.addActionListener(new TestListener());
--------------------------------------------------
java内置的观察者模式Observer接口与Observable不再详述
--------------------------------------------------
观察者模式伪代码:
被观察者:气象站
观察者:3个布告板,目前状况布告板,统计布告板,预测布告板
实现气象站:
首先,为了松耦合,建立接口。
主题接口:
public interface Subject{
public void registerObserver(Observer o);//注册观察者
public void removeObserver(Observer o);//删除观察者
public void notifyObservers();//当主题状态改变时,这个方法会被调用,以通知所有的观察者
}
public interface Observer{
//观察者接口函数,主题状态改变时,调用此函数
public void update(float temp, float humidity, float pressure);
}
public interface DisplayElement{
public void display();//当布告板需要显示时,调用此方法。
}
在WeatherData中实现主题接口
public class WeatherData implements Subject {
private ArrayList observers;//记录观察者
private temperature;
private humidity;
private pressure;
public WeatherData()
{
observers = new ArrayList();
}
public void registerObserver(Observer o)
{
observers.add(o);
}
public void removeObserver(Observer o)
{
int i = observers.indeOf(o);
if(i >= 0)
{
observers.remove(i);
}
}
public void notifyObservers()
{
for(int i=0;i <observers.size();i++)
{
Observer ob = (Observer)observers.get(i);
observers.update(temperature, humidity, pressure);//通知观察者
}
}
public void changeData(float temp, float humidity, float pressure)
{
this.temp = temp;
this.humidity = humidity;
this.pressure = pressure;
notifyObservers();//通知观察者
}
}
实现布告板:
目前状况布告板
public class CurrentConditionsDisplay implements Observer, DisplayElement()
{
private float temperature;
private float humidity;
private Subjuct weatherData;
public CurrentConditionsDisplay(Subjuct weatherData)
{
this.weatherData = weatherData;
weatherData.registerObserver(this);//注册观察者
}
public void update(float temp, float humidity, float pressure)
{
this.temperature = temp;
this.humidity = humidity;
display();
}
public void display()
{
//...
}
}
统计布告板
public class StatisticsDisplay implements Observer, DisplayElement()
{
private float temperature;
private float humidity;
private float pressure;
private Subjuct weatherData;
public StatisticsDisplay(Subjuct weatherData)
{
this.weatherData = weatherData;
weatherData.registerObserver(this);//注册观察者
}
public void update(float temp, float humidity, float pressure)
{
this.temperature = temp;
this.humidity = humidity;
this.pressure = pressure;
display();
}
public void display()
{
//...
}
}
建立测试程序,启动气象站。
public class WeatherStation{
public static void main(String[] args)
{
Subject weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);
weatherData.changeData(88, 70, 30.3f);
}
}