观察者模式结构:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DesignPattern.BehavioralPattern 8 { 9 #region 观察者模式要点 10 //定义:观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象, 11 //这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己的行为。 12 // 13 // 14 //使用场景:1.当一个对象状态的改变需要改变其他对象或实际对象是事先未知的或动态变化的时。 15 //2.当应用中的一些对象必须观察其他对象时,但仅能在有限时间内或特定情况下使用。
订阅列表是动态的, 因此订阅者可随时加入或离开该列表。 16 // 17 //实现方式: 18 /* 19 1.仔细检查你的业务逻辑,试着将其拆分为两个部分:独立于其他代码的核心功能将作为发布者;其他代码则将转化为一组订阅类。 20 21 2.声明订阅者接口。该接口至少应声明一个 update方法。 22 23 3.声明发布者接口并定义一些接口来在列表中添加和删除订阅对象。记住发布者必须仅通过订阅者接口与它们进行交互。 24 25 4.确定存放实际订阅列表的位置并实现订阅方法。 26 通常所有类型的发布者代码看上去都一样, 因此将列表放置在直接扩展自发布者接口的抽象类中是显而易见的。
具体发布者会扩展该类从而继承所有的订阅行为。 27 但是, 如果你需要在现有的类层次结构中应用该模式,则可以考虑使用组合的方式:
将订阅逻辑放入一个独立的对象,然后让所有实际订阅者使用该对象。 28 29 5.创建具体发布者类。 每次发布者发生了重要事件时都必须通知所有的订阅者。 30 31 6.在具体订阅者类中实现通知更新的方法。 绝大部分订阅者需要一些与事件相关的上下文数据。
这些数据可作为通知方法的参数来传递。 32 但还有另一种选择。订阅者接收到通知后直接从通知中获取所有数据,此时发布者必须通过更新方法将自身传递出去。 33 另一种不太灵活的方式是通过构造函数将发布者与订阅者永久性地连接起来。 34 35 7.客户端必须生成所需的全部订阅者, 并在相应的发布者处完成注册工作。 36 37 */ 38 39 #endregion 40 41 42 //订阅者 (Subscriber) 接口声明了通知接口。 43 //在绝大多数情况下, 该接口仅包含一个 update更新方法。 44 //该方法可以拥有多个参数, 使发布者能在更新时传递事件的详细信息。 45 public interface IObserverPattern 46 { 47 void Update(ISubject subject); 48 } 49 50 //具体订阅者 (Concrete Subscribers) 可以执行一些操作来回应发布者的通知。 51 //所有具体订阅者类都实现了同样的接口, 因此发布者不需要与具体类相耦合。 52 public class Observer : IObserverPattern 53 { 54 //订阅者通常需要一些上下文信息来正确地处理更新。 55 //因此, 发布者通常会将一些上下文数据作为通知方法的参数进行传递。 56 //发布者也可将自身作为参数进行传递, 使订阅者直接获取所需的数据。 57 public void Update(ISubject subject) 58 { 59 if ((subject as Subject).State == 0 || (subject as Subject).State >= 2) 60 { 61 Console.WriteLine("Observer Update: Reacted to the event."); 62 } 63 } 64 } 65 66 public interface ISubject 67 { 68 void Subscribe(IObserverPattern observer); 69 void UnSubscribe(IObserverPattern observer); 70 71 void Notify(); 72 73 } 74 75 //发布者 (Publisher) 会向其他对象发送值得关注的事件。 76 //事件会在发布者自身状态改变或执行特定行为后发生。 77 //发布者中包含一个允许新订阅者加入和当前订阅者离开列表的订阅构架。 78 public class Subject : ISubject 79 { 80 List<IObserverPattern> _observers = new List<IObserverPattern>(); 81 private int _state = 0; 82 public int State 83 { 84 get { return _state; } 85 set { _state = value; } 86 } 87 88 //当新事件发生时, 发送者会遍历订阅列表并调用每个订阅者对象的通知方法。 89 //该方法是在订阅者接口中声明的。 90 public void Notify() 91 { 92 foreach (var observer in _observers) 93 { 94 observer.Update(this); 95 } 96 } 97 98 public void Subscribe(IObserverPattern observer) 99 { 100 _observers.Add(observer); 101 Console.WriteLine("Subscribe..."); 102 } 103 104 public void UnSubscribe(IObserverPattern observer) 105 { 106 _observers.Remove(observer); 107 Console.WriteLine("UnSubscribe..."); 108 } 109 110 public void DoBusnessLogicToChangeState(int newstate) 111 { 112 Console.WriteLine("DoBusnessLogicToChangeState..."); 113 this._state = newstate; 114 this.Notify(); 115 } 116 } 117 118 //客户端 (Client) 会分别创建发布者和订阅者对象, 然后为订阅者注册发布者更新。 119 public class ObserverPatternClient 120 { 121 public static void Test() 122 { 123 IObserverPattern observer = new Observer(); 124 Subject subject = new Subject(); 125 subject.Subscribe(observer); 126 127 subject.DoBusnessLogicToChangeState(3); 128 } 129 } 130 }