经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
设计模式-行为型-观察者模式
来源:cnblogs  作者:酷学大叔  时间:2019/10/8 9:27:47  对本文有异议

观察者模式(Observer):

  指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

观察者模式的角色:

   

  1)抽象目标(Subject):也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。 

  2)具体目标(ConcreteSubject):也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。 

  3)抽象观察者(Observer):它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。 

  4)具体观察者(ConcreteObserver):实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。 

  1. 1 internal class Program
  2. 2 {
  3. 3 private static void Main(string[] args)
  4. 4 {
  5. 5 Subject subject = new ConcreteSubject();
  6. 6 Observer observer1 = new ConcreteObserver1();
  7. 7 Observer observer2 = new ConcreteObserver2();
  8. 8 subject.Attach(observer1);
  9. 9 subject.Attach(observer2);
  10. 10 subject.Notify();
  11. 11 }
  12. 12 }
  13. 13
  14. 14 /// <summary>
  15. 15 /// 抽象目标
  16. 16 /// </summary>
  17. 17 internal abstract class Subject
  18. 18 {
  19. 19 /// <summary>
  20. 20 /// 新增观察者
  21. 21 /// </summary>
  22. 22 /// <param name="o"></param>
  23. 23 public abstract void Attach(Observer o);
  24. 24
  25. 25 /// <summary>
  26. 26 /// 删除观察者
  27. 27 /// </summary>
  28. 28 /// <param name="o"></param>
  29. 29 public abstract void Detach(Observer o);
  30. 30
  31. 31 /// <summary>
  32. 32 /// 通知观察者
  33. 33 /// </summary>
  34. 34 public abstract void Notify();
  35. 35 }
  36. 36
  37. 37 /// <summary>
  38. 38 /// 抽象观察者
  39. 39 /// </summary>
  40. 40 internal abstract class Observer
  41. 41 {
  42. 42 public abstract void update();
  43. 43 }
  44. 44
  45. 45 /// <summary>
  46. 46 /// 具体目标
  47. 47 /// </summary>
  48. 48 internal class ConcreteSubject : Subject
  49. 49 {
  50. 50 private System.Collections.Generic.List<Observer> observers
  51. 51 = new System.Collections.Generic.List<Observer>();
  52. 52
  53. 53 public override void Attach(Observer o)
  54. 54 {
  55. 55 if (o != null)
  56. 56 observers.Add(o);
  57. 57 }
  58. 58
  59. 59 public override void Detach(Observer o)
  60. 60 {
  61. 61 if (o != null)
  62. 62 observers.Remove(o);
  63. 63 }
  64. 64
  65. 65 public override void Notify()
  66. 66 {
  67. 67 Console.WriteLine("目标发生变化");
  68. 68 foreach (var observer in observers)
  69. 69 {
  70. 70 observer.update();
  71. 71 }
  72. 72 }
  73. 73 }
  74. 74
  75. 75 /// <summary>
  76. 76 /// 具体观察者1
  77. 77 /// </summary>
  78. 78 internal class ConcreteObserver1 : Observer
  79. 79 {
  80. 80 public override void update()
  81. 81 {
  82. 82 Console.WriteLine("观察者1更新");
  83. 83 }
  84. 84 }
  85. 85
  86. 86 /// <summary>
  87. 87 /// 具体观察者2
  88. 88 /// </summary>
  89. 89 internal class ConcreteObserver2 : Observer
  90. 90 {
  91. 91 public override void update()
  92. 92 {
  93. 93 Console.WriteLine("观察者2更新");
  94. 94 }
  95. 95 }

 事例:

  学校的“铃”是事件源和目标,"学生"是事件监听器和具体观察者,"铃声"是事件类。当下课时间到,会触发铃发声,这时会生成“铃声”事件;学生就会做一些事情。。。

  1. 1 internal class Program
  2. 2 {
  3. 3 private static void Main(string[] args)
  4. 4 {
  5. 5 // 创建下课铃声
  6. 6 Bell subject = new FinishClassBell();
  7. 7 // 创建观察者
  8. 8 Observer xiaoming = new XiaoMing();
  9. 9 Observer xiaohong = new XiaoHong();
  10. 10 Observer xiaowang = new XiaoWang();
  11. 11 // 观察者随着听着下课铃
  12. 12 subject.Attach(xiaoming);
  13. 13 subject.Attach(xiaohong);
  14. 14 subject.Attach(xiaowang);
  15. 15 // 下课铃响了,通知大家
  16. 16 subject.Notify();
  17. 17 }
  18. 18 }
  19. 19
  20. 20 /// <summary>
  21. 21 /// 铃声:抽象目标
  22. 22 /// </summary>
  23. 23 internal abstract class Bell
  24. 24 {
  25. 25 /// <summary>
  26. 26 /// 新增观察者
  27. 27 /// </summary>
  28. 28 /// <param name="o"></param>
  29. 29 public abstract void Attach(Observer o);
  30. 30
  31. 31 /// <summary>
  32. 32 /// 删除观察者
  33. 33 /// </summary>
  34. 34 /// <param name="o"></param>
  35. 35 public abstract void Detach(Observer o);
  36. 36
  37. 37 /// <summary>
  38. 38 /// 通知观察者
  39. 39 /// </summary>
  40. 40 public abstract void Notify();
  41. 41 }
  42. 42
  43. 43 /// <summary>
  44. 44 /// 同学下课做事情:抽象观察者
  45. 45 /// </summary>
  46. 46 internal abstract class Observer
  47. 47 {
  48. 48 public abstract void DoSomeThings();
  49. 49 }
  50. 50
  51. 51 /// <summary>
  52. 52 /// 下课铃声:具体目标
  53. 53 /// </summary>
  54. 54 internal class FinishClassBell : Bell
  55. 55 {
  56. 56 private System.Collections.Generic.List<Observer> observers
  57. 57 = new System.Collections.Generic.List<Observer>();
  58. 58
  59. 59 public override void Attach(Observer o)
  60. 60 {
  61. 61 if (o != null)
  62. 62 observers.Add(o);
  63. 63 }
  64. 64
  65. 65 public override void Detach(Observer o)
  66. 66 {
  67. 67 if (o != null)
  68. 68 observers.Remove(o);
  69. 69 }
  70. 70
  71. 71 public override void Notify()
  72. 72 {
  73. 73 Console.WriteLine("铃声响了...");
  74. 74 foreach (var observer in observers)
  75. 75 {
  76. 76 observer.DoSomeThings();
  77. 77 }
  78. 78 }
  79. 79 }
  80. 80
  81. 81 /// <summary>
  82. 82 /// 小明同学
  83. 83 /// </summary>
  84. 84 internal class XiaoMing : Observer
  85. 85 {
  86. 86 public override void DoSomeThings()
  87. 87 {
  88. 88 Console.WriteLine("小明同学:下课打篮球");
  89. 89 }
  90. 90 }
  91. 91
  92. 92 /// <summary>
  93. 93 /// 小红同学
  94. 94 /// </summary>
  95. 95 internal class XiaoHong : Observer
  96. 96 {
  97. 97 public override void DoSomeThings()
  98. 98 {
  99. 99 Console.WriteLine("小红同学:呜呜呜,还有一节课");
  100. 100 }
  101. 101 }
  102. 102
  103. 103 /// <summary>
  104. 104 /// 小王同学
  105. 105 /// </summary>
  106. 106 internal class XiaoWang : Observer
  107. 107 {
  108. 108 public override void DoSomeThings()
  109. 109 {
  110. 110 Console.WriteLine("小王同学:饿死了,开吃...");
  111. 111 }
  112. 112 }

观察者模式的应用场景:

  1)对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。

  2)当一个抽象模型有两个方面,其中一个方面依赖于另一方面时,可将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。

观察者模式的优缺点:

  优点:观察者和被观察者是抽象耦合的;建立的一套触发机制。

  缺点:

    1)如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

    2)如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。

    3)观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

.NET中观察者模式的应用:

  1. 1 // 委托充当订阅者接口类
  2. 2 public delegate void NotifyEventHandler(object sender);
  3. 3
  4. 4 // 抽象订阅号类
  5. 5 public class TenXun
  6. 6 {
  7. 7 public NotifyEventHandler NotifyEvent;
  8. 8
  9. 9 public string Symbol { get; set; }
  10. 10 public string Info { get; set; }
  11. 11 public TenXun(string symbol, string info)
  12. 12 {
  13. 13 this.Symbol = symbol;
  14. 14 this.Info = info;
  15. 15 }
  16. 16
  17. 17 // 新增对订阅号列表的维护操作
  18. 18 public void AddObserver(NotifyEventHandler ob)
  19. 19 {
  20. 20 NotifyEvent += ob;
  21. 21 }
  22. 22 // 删除对订阅号列表的维护操作
  23. 23 public void RemoveObserver(NotifyEventHandler ob)
  24. 24 {
  25. 25 NotifyEvent -= ob;
  26. 26 }
  27. 27 // 推送消息
  28. 28 public void Update()
  29. 29 {
  30. 30 if (NotifyEvent != null)
  31. 31 {
  32. 32 NotifyEvent(this);
  33. 33 }
  34. 34 }
  35. 35 }
  36. 36
  37. 37 // 具体订阅号类
  38. 38 public class TenXunGame : TenXun
  39. 39 {
  40. 40 public TenXunGame(string symbol, string info)
  41. 41 : base(symbol, info)
  42. 42 {
  43. 43 }
  44. 44 }
  45. 45
  46. 46 // 具体订阅者类
  47. 47 public class Subscriber
  48. 48 {
  49. 49 public string Name { get; set; }
  50. 50 public Subscriber(string name)
  51. 51 {
  52. 52 this.Name = name;
  53. 53 }
  54. 54
  55. 55 public void ReceiveAndPrint(Object obj)
  56. 56 {
  57. 57 TenXun tenxun = obj as TenXun;
  58. 58
  59. 59 if (tenxun != null)
  60. 60 {
  61. 61 Console.WriteLine("Notified {0} of {1}'s" + " Info is: {2}", Name, tenxun.Symbol, tenxun.Info);
  62. 62 }
  63. 63 }
  64. 64 }
  65. 65
  66. 66 static void Main(string[] args)
  67. 67 {
  68. 68 TenXun tenXun = new TenXunGame("TenXun Game", "Have a new game published ....");
  69. 69 Subscriber lh = new Subscriber("Learning Hard");
  70. 70 Subscriber tom = new Subscriber("Tom");
  71. 71
  72. 72 // 添加订阅者
  73. 73 tenXun.AddObserver(new NotifyEventHandler(lh.ReceiveAndPrint));
  74. 74 tenXun.AddObserver(new NotifyEventHandler(tom.ReceiveAndPrint));
  75. 75 tenXun.Update();
  76. 76
  77. 77 Console.WriteLine("-----------------------------------");
  78. 78 Console.WriteLine("移除Tom订阅者");
  79. 79 tenXun.RemoveObserver(new NotifyEventHandler(tom.ReceiveAndPrint));
  80. 80 tenXun.Update();81 }

  从上面代码可以看出,使用事件和委托实现的观察者模式中,减少了订阅者接口类的定义,此时,.NET中的委托正式充到订阅者接口类的角色。使用委托和事件,确实简化了观察者模式的实现,减少了一个IObserver接口的定义。

 参考:https://www.cnblogs.com/zhili/p/ObserverPattern.html

原文链接:http://www.cnblogs.com/az4215/p/11627162.html

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

本站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号