观察者模式

观察者模式定义了一系列对象之间的一对多关系。

当一个对象改变状态其他依赖者都会收到通知。

一对多:
利用观察者模式,主题是具有状态的对象,并且可以控制状态。也就是说,有“一个”
具有状态的主题。另一方面,观察者使用这些状态,虽然这些状态并不属于它们。有
许多的观察者,依赖主题来告诉她们状态何时改变了。这就产生一个关系:“一个”主题对
“多个”观察者的关系。

松耦合:
改变主题或观察者其中一方,并不会影响另一方。

松耦合的设计之所以能让我们建立富有弹性的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);
  }
}

posted on 2018-01-23 15:22  邶风  阅读(185)  评论(0编辑  收藏  举报