经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
Java设计模式之观察者模式
来源:jb51  时间:2021/12/31 8:40:53  对本文有异议

一、观察者模式的定义和特点

观察者模式的定义:

指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。

特点:

降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。

目标与观察者之间建立了一套触发机制。

二、观察者模式的结构

实现观察者模式时要注意具体目标对象和具体观察者对象之间不能直接调用,否则将使两者之间紧密耦合起来,这违反了面向对象的设计原则。 观察者模式的主要角色如下。

  • Subject类:他把所有对观察者对象的引用保存在一个聚合里,每个主题都可以有任何数量的观察者,抽象主题提供一个接口,可以增加和删除任意的观察者对象
  • observer类:抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己
  • ConcreteSubject:具体主题,将有关状态存入具体观察者对象,在具体主题的内部状态改变时,给所有登记过的的观察者发出通知
  • ConcreteObserver:具体观察者,实现抽象观察者角色所要求的的更新接口,以便使本身的状态与主题的状态向协调

三、代码实例

现在有一个需求,各网站需要订阅天气需求, 我们这边要及时更新并发送天气信息,且我们可以自由的注册或者移除想要发送的网站,用观察者模式实现。

如果我们用传统的模式实现该案例,那么会出现一个问题,就是如果我们要修改网站,那可能回去改动网站类的代码,和我们操作更新数据的代码,这不符合我们的开闭原则,因此我们采用观察者模式去实现,因为他也是一种一对多的依赖关系,生活中这种案例多不胜数,例如订阅杂志,等。

结构图如下

代码示例

抽象目标类Subject

  1. package com.observerPattern.weatherCase;
  2. /**
  3. * @author wang
  4. * @version 1.0
  5. * @packageName com.observerPattern.weatherCase
  6. * @className Subject
  7. * @date 2021/12/28 15:49
  8. * @Description Subject抽象目标类,由具体的目标去实现
  9. */
  10. public interface Subject {
  11. /**
  12. * @Date 2021/12/28 16:20
  13. * @Param
  14. * @param o
  15. * @Return void
  16. * @MetodName registerObserver
  17. * @Author wang
  18. * @Description 注册观察者方法
  19. */
  20. void registerObserver(Observer o);
  21. /**
  22. * @Date 2021/12/28 16:20
  23. * @Param
  24. * @param o
  25. * @Return void
  26. * @MetodName removeObserver
  27. * @Author wang
  28. * @Description 移除观察者
  29. */
  30. void removeObserver(Observer o);
  31. /**
  32. * @Date 2021/12/28 16:20
  33. * @Param
  34. * @Return void
  35. * @MetodName notifyObservers
  36. * @Author wang
  37. * @Description 通知观察者
  38. */
  39. void notifyObservers();
  40. }

具体目标WeatherDate类

  1. package com.observerPattern.weatherCase;
  2. import java.util.ArrayList;
  3. /**
  4. * @author wang
  5. * @version 1.0
  6. * @packageName com.observerPattern.weatherCase
  7. * @className WeatherDate
  8. * @date 2021/12/28 16:00
  9. * @Description 包含最新的天气数据,是具体的目标,实现了抽象目标subject
  10. * 该类含有观察者集合,使用ArrayLis集合管理.
  11. * 当数据有更新时,就主动的调用ArrayList集合通知各个观察者
  12. *
  13. */
  14. public class WeatherDate implements Subject{
  15. private float temperature;
  16. private float pressure;
  17. private float humidity;
  18. private ArrayList<Observer> observers;
  19. /**
  20. * @Date 2021/12/28 16:10
  21. * @Param
  22. * @Return null
  23. * @MetodName WeatherDate
  24. * @Author wang
  25. * @Description 初始化观察者集合
  26. */
  27. public WeatherDate() {
  28. this.observers = new ArrayList<Observer>();
  29. }
  30. public float getTemperature() {
  31. return temperature;
  32. }
  33. public float getPressure() {
  34. return pressure;
  35. }
  36. public float getHumidity() {
  37. return humidity;
  38. }
  39. /**
  40. * @Date 2021/12/28 16:10
  41. * @Param
  42. * @Return void
  43. * @MetodName dateChange
  44. * @Author wang
  45. * @Description 调用通知方法,将更新后的数据推送至各个观察者
  46. */
  47. public void dateChange() {
  48. notifyObservers();
  49. }
  50. /**
  51. * @Date 2021/12/28 16:11
  52. * @Param
  53. * @param temperature
  54. * @param pressure
  55. * @param humidity
  56. * @Return void
  57. * @MetodName setDate
  58. * @Author wang
  59. * @Description 更新数据
  60. */
  61. public void setDate(float temperature,float pressure,float humidity) {
  62. this.temperature = temperature;
  63. this.pressure = pressure;
  64. this.humidity = humidity;
  65. dateChange();
  66. }
  67. /**
  68. * @Date 2021/12/28 16:11
  69. * @Param
  70. * @param o
  71. * @Return void
  72. * @MetodName registerObserver
  73. * @Author wang
  74. * @Description z注册一个观察者
  75. */
  76. @Override
  77. public void registerObserver(Observer o) {
  78. observers.add(o);
  79. }
  80. /**
  81. * @Date 2021/12/28 16:11
  82. * @Param
  83. * @param o
  84. * @Return void
  85. * @MetodName removeObserver
  86. * @Author wang
  87. * @Description 移除一个观察者
  88. */
  89. @Override
  90. public void removeObserver(Observer o) {
  91. if(observers.contains(o)) {
  92. observers.remove(o);
  93. }
  94. }
  95. /**
  96. * @Date 2021/12/28 16:12
  97. * @Param
  98. * @Return void
  99. * @MetodName notifyObservers
  100. * @Author wang
  101. * @Description 通知观察者
  102. */
  103. @Override
  104. public void notifyObservers() {
  105. for(int i = 0;i< observers.size();i++) {
  106. observers.get(i).update(this.temperature,this.pressure,this.humidity);
  107. }
  108. }
  109. }

抽象观察者Observer:

  1. package com.observerPattern.weatherCase;
  2. /**
  3. * @author wang
  4. * @version 1.0
  5. * @packageName com.observerPattern.weatherCase
  6. * @className Observer
  7. * @date 2021/12/28 15:50
  8. * @Description 观察者接口,方法更新温度,压力,湿度,由具体的观察者实现
  9. */
  10. public interface Observer {
  11. /**
  12. * @Date 2021/12/28 16:18
  13. * @Param
  14. * @param temperature
  15. * @param pressure
  16. * @param humidity
  17. * @Return void
  18. * @MetodName update
  19. * @Author wang
  20. * @Description
  21. */
  22. void update(float temperature,float pressure,float humidity);
  23. }

具体观察者1

  1. package com.observerPattern.weatherCase;
  2. /**
  3. * @author wang
  4. * @version 1.0
  5. * @packageName com.observerPattern.weatherCase
  6. * @className CurrentCondition
  7. * @date 2021/12/28 15:54
  8. * @Description 具体的一个观察者类,表示当前天气情况,实现观察者接口
  9. */
  10. public class CurrentCondition implements Observer{
  11. private float temperature;
  12. private float pressure;
  13. private float humidity;
  14. /**
  15. * @Date 2021/12/28 15:58
  16. * @Param
  17. * @param temperature
  18. * @param pressure
  19. * @param humidity
  20. * @Return void
  21. * @MetodName update
  22. * @Author wang
  23. * @Description该方法将更新后的数据推送至该观察者,观察者打印
  24. */
  25. @Override
  26. public void update(float temperature, float pressure, float humidity) {
  27. this.temperature = temperature;
  28. this.pressure = pressure;
  29. this.humidity = humidity;
  30. display();
  31. }
  32. /**
  33. * @Date 2021/12/28 15:59
  34. * @Param
  35. * @Return void
  36. * @MetodName display
  37. * @Author wang
  38. * @Description 该方法显示更新的数据
  39. */
  40. public void display() {
  41. System.out.println("测试显示当前气温:" + temperature + "度");
  42. System.out.println("测试显示当前压力:" + pressure + "帕");
  43. System.out.println("测试显示当前湿度:" + humidity + "Rh");
  44. }
  45. }

具体观察者2:

  1. package com.observerPattern.weatherCase;
  2. /**
  3. * @author wang
  4. * @version 1.0
  5. * @packageName com.observerPattern.weatherCase
  6. * @className SinaNet
  7. * @date 2021/12/28 16:21
  8. * @Description 新浪网站作为一个观察者
  9. */
  10. public class SinaNet implements Observer{
  11. private float temperature;
  12. private float pressure;
  13. private float humidity;
  14. /**
  15. * @Date 2021/12/28 15:58
  16. * @Param
  17. * @param temperature
  18. * @param pressure
  19. * @param humidity
  20. * @Return void
  21. * @MetodName update
  22. * @Author wang
  23. * @Description该方法将更新后的数据推送至该观察者,观察者打印
  24. */
  25. @Override
  26. public void update(float temperature, float pressure, float humidity) {
  27. this.temperature = temperature;
  28. this.pressure = pressure;
  29. this.humidity = humidity;
  30. display();
  31. }
  32. /**
  33. * @Date 2021/12/28 15:59
  34. * @Param
  35. * @Return void
  36. * @MetodName display
  37. * @Author wang
  38. * @Description 该方法显示更新的数据
  39. */
  40. public void display() {
  41. System.out.println("=======新浪网站=======");
  42. System.out.println("新浪显示当前气温:" + temperature + "度");
  43. System.out.println("新浪显示当前压力:" + pressure + "帕");
  44. System.out.println("新浪显示当前湿度:" + humidity + "Rh");
  45. }
  46. }

客户端测试类

  1. package com.observerPattern.weatherCase;
  2. /**
  3. * @author wang
  4. * @version 1.0
  5. * @packageName com.observerPattern.weatherCase
  6. * @className ClientTest
  7. * @date 2021/12/28 16:12
  8. * @Description 客户端测试代码,测试观察者模式
  9. */
  10. public class ClientTest {
  11. public static void main(String[] args) {
  12. //创建一个weatherDate具体目标
  13. WeatherDate weatherDate = new WeatherDate();
  14. //创建一个观察者
  15. CurrentCondition currentCondition = new CurrentCondition();
  16. //注册一个观察者
  17. weatherDate.registerObserver(currentCondition);
  18. //注册新浪
  19. SinaNet sinaNet = new SinaNet();
  20. weatherDate.registerObserver(sinaNet);
  21. //测试更新
  22. System.out.println("通知给各观察者");
  23. weatherDate.setDate(3,65,12);
  24. //测试移除
  25. weatherDate.removeObserver(currentCondition);
  26. System.out.println("========================");
  27. System.out.println("第二次更新");
  28. weatherDate.setDate(6,88,16);
  29. }
  30. }
  31. /*
  32. 通知给各观察者
  33. 测试显示当前气温:3.0度
  34. 测试显示当前压力:65.0帕
  35. 测试显示当前湿度:12.0Rh
  36. =======新浪网站=======
  37. 新浪显示当前气温:3.0度
  38. 新浪显示当前压力:65.0帕
  39. 新浪显示当前湿度:12.0Rh
  40. ========================
  41. 第二次更新
  42. =======新浪网站=======
  43. 新浪显示当前气温:6.0度
  44. 新浪显示当前压力:88.0帕
  45. 新浪显示当前湿度:16.0Rh
  46. */

这种好处是我们如果有新的网站的加入,那么直接添加一个观察者类即可,不用修改代码

以及删除,注册都是独立开来的。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注w3xue的更多内容!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号