观察者模式(也称为发布/订阅模式)提供了避免组件之间紧密耦合的另一种方法,它将观察者和被观察的对象分离开。在该模式中,一个对象通过添加一个方法(该方法允许另一个对象,即观察者注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到己注册的观察者。这些观察者收到消息后所执行的操作与可观察的对象无关,这种模式使得对象可以相互对话,而不必了解原因。Java语言与C#语言的事件处理机制就是采用此种设计模式。
例如,用户界面(同一个数据可以有多种不同的显示方式)可以作为观察者,业务数据是被观察者,当数据有变化后会通知界面,界面收到通知后,会根据自己的显示方式修改界面的显示。面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面。一个对象只做一件事情,并且将它做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。设计类图如下图所示。
观察者模式设计类图 下面给出一个观察者模式的示例代码,代码的主要功能是实现天气预报,同样的温度信息可以有多种不同的展示方式:
import java.util.ArrayList;
interface Subject
{
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
class Whether implements Subject
{
private ArrayList<Observer>observers=new ArrayList<Observer>();
private float temperature;
@Override
public void notifyObservers() {
for(int i=0;i<this.observers.size();i++)
{
this.observers.get(i).update(temperature);
}
}
@Override
public void registerObserver(Observer o) {
this.observers.add(o);
}
@Override
public void removeObserver(Observer o) {
this.observers.remove(o);
}
public void whetherChange() {
this.notifyObservers();
}
public float getTemperature() {
return temperature;
}
public void setTemperature(float temperature) {
this.temperature=temperature;
notifyObservers();
}
}
interface Observer
{
//更新温度
public void update(float temp);
}
class WhetherDisplayl implements Observer
{
private float temprature;
public WhetherDisplay1(Subject whether) {
whether.registerObserver(this);
}
@Override
public void update(float temp) {
this.temprature=temp;
display();
}
public void display() {
System.out.println("display1****:"+this.temprature);
}
}
class WhetherDisplay2 implements Observer
{
private float temprature;
public WhetherDisplay2(Subject whether)
{
whether.registerObserver(this);
}
@Override
public void update(float temp) {
this.temprature=temp;
display();
}
public void display()
{
System.out.println("display2----:"+this.temprature);
}
}
public class Test
{
public static void main(String[] args)
{
Whether whether=new Whether();
WhetherDisplay1 d1=new WhetherDisplay1(whether);
WhetherDisplay2 d2=new WhetherDisplay2(whether);
whether.setTemperature(27);
whether.setTemperature(26);
}
}