Skip to main content

观察者模式

Published: 2020-11-19

使用场景 #

目标对象的接口 #

class Subject {
 public:
  virtual ~Subject() {}
  virtual void registerObserver(Observer *o) = 0;
  virtual void removeObserver(Observer *o) = 0;
  virtual void notifyObservers() = 0;
};

具体的目标对象 #

class WeatherData : public Subject {
 public:
  WeatherData();
  virtual ~WeatherData();
  virtual void registerObserver(Observer *o);
  virtual void removeObserver(Observer *o);
  virtual void notifyObservers();
  void measurementsChanged();
  void setMeasurements(float temperature, float humidity, float pressure);
  float temperature();
  float humidity();
  float pressure();
 private:
  std::vector<Observer*> *observers_;
  float temperature_;
  float humidity_;
  float pressure_;
};
void WeatherData::notifyObservers() {
  int i;
  for (i = 0; i < observers_->size(); ++i) {
    Observer* observer = (*observers_)[i];
    observer->update(temperature_, humidity_, pressure_);
  }
}

void WeatherData::measurementsChanged() {
  notifyObservers();
}

void WeatherData::setMeasurements(float temperature, float humidity,
                                  float pressure) {
  temperature_ = temperature;
  humidity_ = humidity;
  pressure_ = pressure;
  measurementsChanged();
}

观察者更新接口 #

class Observer {
 public:
  virtual ~Observer() {}
  virtual void update(float temp, float humdity, float pressure) = 0;
};

观察者显示接口 #

class DisplayElement {
 public:
  virtual ~DisplayElement() {} 
  virtual void display() = 0;
};

具体的观察者 #

class StatisticsDisplay : public Observer, public DisplayElement {
 public:
  explicit StatisticsDisplay(Subject *weather_data);
  ~StatisticsDisplay();
  virtual void update(float temp, float humidity, float pressure);
  virtual void display();
 private:
  float max_temp_;
  float min_temp_;
  float temp_sum_;
  int num_readings_;
  Subject *weather_data_;
  DISALLOW_COPY_AND_ASSIGN(StatisticsDisplay);
};
StatisticsDisplay::StatisticsDisplay(Subject *weather_data)
    : weather_data_(weather_data), max_temp_(0.0f), min_temp_(200),
      temp_sum_(0.0f), num_readings_(0) {
  weather_data_->registerObserver(this);
}

void StatisticsDisplay::update(float temp, float humidity, float pressure) {
  temp_sum_ += temp;
  num_readings_++;

  if (temp > max_temp_) {
    max_temp_ = temp;
  }
  if (temp < min_temp_) {
    min_temp_ = temp;
  }
  display();
}

void StatisticsDisplay::display() {
  printf("Avg/Max/Min temperature = %f/%f/%f\n", (temp_sum_ / num_readings_),
         max_temp_, min_temp_);
}

测试 #

int main(int argc, char *argv[]) {
  WeatherData *weather_data = new WeatherData();

  CurrentConditionsDisplay *current_display =
      new CurrentConditionsDisplay(weather_data);
  StatisticsDisplay *statistics_display =
      new StatisticsDisplay(weather_data);
  ForecastDisplay *forecast_display =
      new ForecastDisplay(weather_data);

  weather_data->setMeasurements(80, 65, 30.4f);
  weather_data->setMeasurements(82, 70, 29.2f);
  weather_data->setMeasurements(78, 90, 29.2f);
}

Next: 有趣的人
Previous: 单例模式