设计模式之观察者模式

小咪咪 2021-11-02 06:14 476阅读 0赞

上一篇:设计模式之策略模式
故事要从气象站说起,气象站有个WeatherData对象,这个对象负责拿到所有的气象数据(温度、湿度、气压),而气象站同时也存在好几个公告板,负责显示气象数据,并且要实时更新。
在这里插入图片描述
很快我们便设计了下面的类图:
在WeatherData类中放一个公布板(CurrentDisplay)属性,在每次数据更新的时候调用notify方法来通知公布版更新实时数据。
在这里插入图片描述
很快的就可以将我们的气象站设计出来,在WeatherData类中放入一个CurrentDisplay对象,每次更新数据就通知我们的公告板对象进行更新数据。

  1. package shejimoshi.Observer;
  2. public class WeatherData {
  3. private float teperature;
  4. private float hunidity;
  5. private float pressure;
  6. private CurrentDisplay display;
  7. WeatherData(CurrentDisplay display){
  8. this.display = display;
  9. }
  10. public void notifyDisplay(){
  11. this.display.update(teperature,hunidity,pressure);
  12. }
  13. public float getTeperature() {
  14. return teperature;
  15. }
  16. public void setTeperature(float teperature) {
  17. this.teperature = teperature;
  18. }
  19. public float getHunidity() {
  20. return hunidity;
  21. }
  22. public void setHunidity(float hunidity) {
  23. this.hunidity = hunidity;
  24. }
  25. public float getPressure() {
  26. return pressure;
  27. }
  28. public void setPressure(float pressure) {
  29. this.pressure = pressure;
  30. }
  31. }
  32. package shejimoshi.Observer;
  33. public class CurrentDisplay {
  34. private float teperature;
  35. private float hunidity;
  36. private float pressure;
  37. public void update(float teperature,float hunidity,float pressure){
  38. this.teperature = teperature;
  39. this.hunidity = hunidity;
  40. this.pressure = pressure;
  41. display();
  42. }
  43. public void display(){
  44. System.out.println("Current conditions:"+teperature+"and "+hunidity+"%humidity");
  45. }
  46. public static void main(String[] args) {
  47. CurrentDisplay display = new CurrentDisplay();
  48. WeatherData data = new WeatherData(display);
  49. data.setTeperature(30);
  50. data.setHunidity(1.1f);
  51. data.setPressure(1.3f);
  52. data.notifyDisplay();
  53. }
  54. }

系统如期上线,刚开始没问题,可是过了一段时间,气象站增加了一个公告板(SecondDisplay)用来显示一些基于观测值(温度,湿度,气压…)的一些计算结果。
这个时候我们就会在我们的WeatherData中在加一个属性SecondDisplay,然后来了几十个显示板,类爆炸了,WeatherData被我们修改的千疮百孔,如果有一天气象站突然不用某个显示板了,又要去修改,完了。
这就违反了设计模式的原则:开闭原则
开闭原则:使软件中的对象对扩展开放,对修改关闭

观察者模式

既然需要很多个显示板,那么观察者模式就在WeatherData中存放一个容器用来存放显示板(Display),然后各个显示板就实现Display接口,再来一个显示板的时候就直接将显示板加入到WeatherData中的容器中,很快就能实现下面的代码:

  1. package shejimoshi.Observer;
  2. //显示板接口
  3. public interface Display {
  4. public void update(float teperature,float hunidity,float pressure);
  5. }
  6. package shejimoshi.Observer;
  7. //主题接口也就是WeatherData实现的接口
  8. public interface Subjcet {
  9. public void registerDisplay(Display d);
  10. public void removeDisplay(Display d);
  11. public void notifyDisplay();
  12. }
  13. package shejimoshi.Observer;
  14. public class CurrentDisplay implements Display{
  15. private float teperature;
  16. private float hunidity;
  17. private float pressure;
  18. public void update(float teperature,float hunidity,float pressure){
  19. this.teperature = teperature;
  20. this.hunidity = hunidity;
  21. this.pressure = pressure;
  22. display();
  23. }
  24. public void display(){
  25. System.out.println("Current conditions:"+teperature+"and "+hunidity+"%humidity");
  26. }
  27. }
  28. package shejimoshi.Observer;
  29. import java.util.ArrayList;
  30. public class WeatherData implements Subjcet{
  31. private float teperature;
  32. private float hunidity;
  33. private float pressure;
  34. private ArrayList displays;
  35. private CurrentDisplay display;
  36. WeatherData(){
  37. displays = new ArrayList();
  38. }
  39. @Override
  40. public void registerDisplay(Display d) {
  41. displays.add(d);
  42. }
  43. @Override
  44. public void removeDisplay(Display d) {
  45. int i = displays.indexOf(d);
  46. if(i>=0){
  47. displays.remove(i);
  48. }
  49. }
  50. public void notifyDisplay(){
  51. for (Object o:displays) {
  52. Display display = (Display)o;
  53. display.update(teperature,hunidity,pressure);
  54. }
  55. }
  56. public float getTeperature() {
  57. return teperature;
  58. }
  59. public void setTeperature(float teperature) {
  60. this.teperature = teperature;
  61. }
  62. public float getHunidity() {
  63. return hunidity;
  64. }
  65. public void setHunidity(float hunidity) {
  66. this.hunidity = hunidity;
  67. }
  68. public float getPressure() {
  69. return pressure;
  70. }
  71. public void setPressure(float pressure) {
  72. this.pressure = pressure;
  73. }
  74. public static void main(String[] args) {
  75. CurrentDisplay display = new CurrentDisplay();
  76. WeatherData data = new WeatherData();
  77. data.registerDisplay(display);
  78. data.setTeperature(30);
  79. data.setHunidity(1.1f);
  80. data.setPressure(1.3f);
  81. data.notifyDisplay();
  82. }
  83. }

这样每来一个显示板就可以将显示板注册到我们的主题(WeatherData)中去,再主题更新数据就会通知显示板来更新数据,如果不需要某个显示板就直接remove掉,很灵活。

推、拉

系统如期上线,顺利运行,突然有一天,一个显示板不高兴了:每次你主题更新的时候都要通知我(),我显得很被动,我需要是,我每次需要数据的时候我自己去拿数据,并且,我如果要不订阅你(remove掉),我需要通知你WeatherData,然后才能remove,我需要的是自己注册与否是我自己来决定,就像订报纸一样,我不订阅了我自己直接取消就好了:

  1. package shejimoshi.Observer;
  2. public class CurrentDisplay implements Display{
  3. private float teperature;
  4. private float hunidity;
  5. private float pressure;
  6. private Subjcet subjcet;
  7. CurrentDisplay(Subjcet subjcet){
  8. this.subjcet = subjcet;
  9. }
  10. public void regist(){
  11. subjcet.registerDisplay(this);
  12. }
  13. public void remove(){
  14. subjcet.removeDisplay(this);
  15. }
  16. public void getData(){
  17. subjcet.notifyDisplay();
  18. }
  19. public void update(float teperature,float hunidity,float pressure){
  20. this.teperature = teperature;
  21. this.hunidity = hunidity;
  22. this.pressure = pressure;
  23. display();
  24. }
  25. public void display(){
  26. System.out.println("Current conditions:"+teperature+"and "+hunidity+"%humidity");
  27. }
  28. }

这样在Display中放入一个WeatherData之后,每个显示板自己就可以决定什么时候需要拿数据(),以及自己决定自己是否订阅这个Subjcet。

最后

在jdk中的观察者模式是这样的:
Observer是个接口,Observable是个类,因为是类,所以不可以在继承Observable的时候再去继承别的类的特性,所以这就有很大的局限性,这边就不具体展开说了。

发表评论

表情:
评论列表 (有 0 条评论,476人围观)

还没有评论,来说两句吧...

相关阅读

    相关 设计模式观察模式

    观察者模式 什么是观察者模式 观察者模式属于行为模式的一种,定义了对象的通用交流方式。 观察者模式定义了一对多的关系,一个对象改变了状态,则其它所有依赖

    相关 设计模式观察模式

    前言 使用场景: 1、拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。 2、西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟

    相关 设计模式观察模式

    当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 即目标发生更

    相关 设计模式观察模式

    定义 当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。观察者模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步

    相关 设计模式观察模式

     今天放假,又有时间继续啃《java设计模式》这本书了。每次学会一种设计模式内心都会有一种小小的成就感,但是懂是懂了,不知道会不会用。主要是现在没有什么项目经验,设计模式学了也

    相关 设计模式观察模式

    [上一篇:设计模式之策略模式][Link 1] 故事要从气象站说起,气象站有个WeatherData对象,这个对象负责拿到所有的气象数据(温度、湿度、气压),而气象站同时也

    相关 设计模式观察模式

    1 观察者模式 当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都

    相关 设计模式——观察模式

    > 设计模式: > > 前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定。而是一套用来提高代码可复用性、可维护性、可读性、稳健性、以及安全性的解决方案