介绍

多个其他类想对某一个类的属性实现同步时使用

原理image-20201013133118936.png

对原理类图的说明-即(命名模式的角色及职责)

  1. Subject接口目的是管理观察者,registerObserver注册观察者,removeObserver移除观察者,notifyObservers通知观察者
  2. 数据源类就是观察者观察的目标,数据源需要提前把观察者注册到observers集合中,当数据源类数据更新时,能自身通知各个观察者或者提供接口让观察者调用查看最新数据。
  3. Observer是观察者的一个抽象接口,update方法是当数据源信息更新时,同步到观察者上的数据的方法

案例

天气预报项目需求,具体要求如下:

  1. 气象站可以将每天测量到的温度,湿度,气压等等以公告的形式发布出去(比如发布到自己的网站或第三方)。
  2. 需要设计开放型API,便于其他第三方也能接入气象站获取数据。
  3. 提供温度、气压和湿度的接口
  4. 测量数据更新时,要能实时的通知给第三方

image-20201013133747462.png

  1. //Subject三个方法都是操作的观察者集合的
  2. public interface Subject {
  3. public void registerObserver(Observer o);
  4. public void removeObserver(Observer o);
  5. public void notifyObservers();
  6. }
  7. //WeatherData(天文台)实现Subject实现操作观察者的方法
  8. public class WeatherData implements Subject{
  9. private double temperature;
  10. private double pressure;
  11. private double humidity;
  12. private ArrayList<Observer> observers = new ArrayList<>();
  13. public double getTemperrature() {
  14. return temperature;
  15. }
  16. public double getPressure() {
  17. return pressure;
  18. }
  19. public double getHumidity() {
  20. return humidity;
  21. }
  22. public void dataChange(){
  23. notifyObservers();
  24. }
  25. public void setWeatherData(double temperature,double pressure,double humidity){
  26. this.temperature = temperature;
  27. this.pressure = pressure;
  28. this.humidity = humidity;
  29. dataChange(); //通知观察者数据改变
  30. }
  31. @Override
  32. public void registerObserver(Observer o) {
  33. observers.add(o);
  34. }
  35. @Override
  36. public void removeObserver(Observer o) {
  37. if (observers.contains(o)){
  38. observers.remove(o);
  39. }
  40. }
  41. @Override
  42. public void notifyObservers() {
  43. for (Observer observer : observers) {
  44. observer.update(this.temperature,this.pressure,this.humidity);
  45. }
  46. }
  47. }
  1. //抽象观察者接口
  2. public interface Observer {
  3. public void update(double temperature,double pressure,double humidity);
  4. }
  5. //新浪观察者实现类
  6. public class xinlang implements Observer{
  7. private double temperature;
  8. private double pressure;
  9. private double humidity;
  10. @Override
  11. public void update(double temperrature, double pressure, double humidity) {
  12. this.temperature = temperrature;
  13. this.pressure = pressure;
  14. this.humidity = humidity;
  15. display();
  16. }
  17. private void display() {
  18. System.out.println("新浪-------温度为 "+ temperature + "度--------");
  19. System.out.println("新浪-------气压为 "+ pressure + "帕--------");
  20. System.out.println("新浪-------湿度为 "+ humidity + "%--------");
  21. }
  22. }
  23. //百度观察者实现类
  24. public class Baidu implements Observer{
  25. private double temperature;
  26. private double pressure;
  27. private double humidity;
  28. @Override
  29. public void update(double temperrature, double pressure, double humidity) {
  30. this.temperature = temperrature;
  31. this.pressure = pressure;
  32. this.humidity = humidity;
  33. display();
  34. }
  35. private void display() {
  36. System.out.println("百度-------温度为 "+ temperature + "度--------");
  37. System.out.println("百度-------气压为 "+ pressure + "帕--------");
  38. System.out.println("百度-------湿度为 "+ humidity + "%--------");
  39. }
  40. }
  1. //Client端测试
  2. public class Client {
  3. public static void main(String[] args) {
  4. //创建WeatherData天气数据对象
  5. WeatherData weatherData = new WeatherData();
  6. //创建观察者
  7. Observer observer1 = new Baidu();
  8. Observer observer2 = new xinlang();
  9. //注册观察者
  10. weatherData.registerObserver(observer1);
  11. weatherData.registerObserver(observer2);
  12. //天文台数据改变
  13. weatherData.setWeatherData(30,150,60);
  14. }
  15. }

只要天文台数据改变就能通知到所有注册的观察者image-20201013134536868.png

观察者模式的好处

  1. 观察者模式设计后,会以集合的方式来管理用户(Observer),包括注册,移除和通知。
  2. 这样,我们增加观察者(这里可以理解成一个新的公告板),就不需要去修改核心类WeatherData不会修改代码,遵守了ocp原则。

个人总结

此模式的核心是使用一个接口把全部观察者统一接管了,再在数据源类中用集合统一管理所有观察者,核心的方法是
1.注册观察者

2.移除观察者

3.通知所有观察者