一起来学习C#的观察者模式
using System; using System.Collections.Generic; public class Example { public static void Main() { BaggageHandler provider = new BaggageHandler(); ArrivalsMonitor observer1 = new ArrivalsMonitor("BaggageClaimMonitor1"); ArrivalsMonitor observer2 = new ArrivalsMonitor("SecurityExit"); // 添加信息,此时没有观察者,对于新的信息不会进行操作,若有观察者,则对观察者内部数据进行对比,若有新内容则进行更新。 provider.BaggageStatus(712, "Detroit", 3); // 添加了观察者,观察者内部也有数据集。新信息传进来,会与内部数据集进行对比,若有新内容则进行更新。 observer1.Subscribe(provider); provider.BaggageStatus(712, "Kalamazoo", 3); provider.BaggageStatus(400, "New York-Kennedy", 1); provider.BaggageStatus(712, "Detroit", 3); observer2.Subscribe(provider); provider.BaggageStatus(511, "San Francisco", 2); //参数3为0 执行移除712对应信息值,对应观察者打印 provider.BaggageStatus(712); observer2.Unsubscribe(); provider.BaggageStatus(400); provider.LastBaggageClaimed(); } } // The example displays the following output: // Arrivals information from BaggageClaimMonitor1 // Detroit 712 3 // // Arrivals information from BaggageClaimMonitor1 // Detroit 712 3 // Kalamazoo 712 3 // // Arrivals information from BaggageClaimMonitor1 // Detroit 712 3 // Kalamazoo 712 3 // New York-Kennedy 400 1 // // Arrivals information from SecurityExit // Detroit 712 3 // // Arrivals information from SecurityExit // Detroit 712 3 // Kalamazoo 712 3 // // Arrivals information from SecurityExit // Detroit 712 3 // Kalamazoo 712 3 // New York-Kennedy 400 1 // // Arrivals information from BaggageClaimMonitor1 // Detroit 712 3 // Kalamazoo 712 3 // New York-Kennedy 400 1 // San Francisco 511 2 // // Arrivals information from SecurityExit // Detroit 712 3 // Kalamazoo 712 3 // New York-Kennedy 400 1 // San Francisco 511 2 // // Arrivals information from BaggageClaimMonitor1 // New York-Kennedy 400 1 // San Francisco 511 2 // // Arrivals information from SecurityExit // New York-Kennedy 400 1 // San Francisco 511 2 // // Arrivals information from BaggageClaimMonitor1 // San Francisco 511 2
using System; using System.Collections.Generic; public class ArrivalsMonitor : IObserver<BaggageInfo> { private string name; private List<string> flightInfos = new List<string>(); private IDisposable cancellation; private string fmt = "{0,-20} {1,5} {2, 3}"; public ArrivalsMonitor(string name) { if (String.IsNullOrEmpty(name)) throw new ArgumentNullException("The observer must be assigned a name."); this.name = name; } public virtual void Subscribe(BaggageHandler provider) { // 参数是处理者! 添加观察者 this cancellation = provider.Subscribe(this); } public virtual void Unsubscribe() { cancellation.Dispose(); flightInfos.Clear(); } public virtual void OnCompleted() { flightInfos.Clear(); } // No implementation needed: Method is not called by the BaggageHandler class. public virtual void OnError(Exception e) { // No implementation. } // Update information. public virtual void OnNext(BaggageInfo info) { bool updated = false; // Flight has unloaded its baggage; remove from the monitor. if (info.Carousel == 0) { var flightsToRemove = new List<string>(); string flightNo = String.Format("{0,5}", info.FlightNumber); foreach (var flightInfo in flightInfos) { if (flightInfo.Substring(21, 5).Equals(flightNo)) { flightsToRemove.Add(flightInfo); updated = true; } } foreach (var flightToRemove in flightsToRemove) flightInfos.Remove(flightToRemove); flightsToRemove.Clear(); } else { // Add flight if it does not exist in the collection. string flightInfo = String.Format(fmt, info.From, info.FlightNumber, info.Carousel); if (!flightInfos.Contains(flightInfo)) { flightInfos.Add(flightInfo); updated = true; } } if (updated) { flightInfos.Sort(); Console.WriteLine("Arrivals information from {0}", this.name); foreach (var flightInfo in flightInfos) Console.WriteLine(flightInfo); Console.WriteLine(); } } }
using System; using System.Collections.Generic; public class BaggageHandler : IObservable<BaggageInfo> { private List<IObserver<BaggageInfo>> observers; private List<BaggageInfo> flights; public BaggageHandler() { observers = new List<IObserver<BaggageInfo>>(); flights = new List<BaggageInfo>(); } public IDisposable Subscribe(IObserver<BaggageInfo> observer) { // Check whether observer is already registered. If not, add it if (!observers.Contains(observer)) { observers.Add(observer); // Provide observer with existing data. foreach (var item in flights) observer.OnNext(item); } return new Unsubscriber<BaggageInfo>(observers, observer); } // Called to indicate all baggage is now unloaded. public void BaggageStatus(int flightNo) { BaggageStatus(flightNo, String.Empty, 0); } public void BaggageStatus(int flightNo, string from, int carousel) { var info = new BaggageInfo(flightNo, from, carousel); // Carousel is assigned, so add new info object to list. if (carousel > 0 && !flights.Contains(info)) { flights.Add(info); foreach (var observer in observers) observer.OnNext(info); } else if (carousel == 0) { // Baggage claim for flight is done var flightsToRemove = new List<BaggageInfo>(); foreach (var flight in flights) { if (info.FlightNumber == flight.FlightNumber) { flightsToRemove.Add(flight); foreach (var observer in observers) observer.OnNext(info); } } foreach (var flightToRemove in flightsToRemove) flights.Remove(flightToRemove); flightsToRemove.Clear(); } } public void LastBaggageClaimed() { foreach (var observer in observers) observer.OnCompleted(); observers.Clear(); } }
using System; using System.Collections.Generic; public class BaggageInfo { private int flightNo; private string origin; private int location; internal BaggageInfo(int flight, string from, int carousel) { this.flightNo = flight; this.origin = from; this.location = carousel; } public int FlightNumber { get { return this.flightNo; } } public string From { get { return this.origin; } } public int Carousel { get { return this.location; } } }
using System; using System.Collections.Generic; internal class Unsubscriber<BaggageInfo> : IDisposable { private List<IObserver<BaggageInfo>> _observers; private IObserver<BaggageInfo> _observer; internal Unsubscriber(List<IObserver<BaggageInfo>> observers, IObserver<BaggageInfo> observer) { this._observers = observers; this._observer = observer; } public void Dispose() { if (_observers.Contains(_observer)) _observers.Remove(_observer); } }
流程简单分析
个人理解
类:
- 核心处理类(控制者/处理者)
- 信息数据列表
- 观察者列表
- 观察者类
- 数据信息类
- 释放空间
流程:
处理者接收新数据判断是否存在,不存在添加到数据列表中,然后遍历观察者列表,根据新数据执行新动作。
观察者类主要实现自身的添加和删除操作,将处理者作为参数传进自身中,调用处理者中的添加观察者函数进行添加绑定。
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!
赞 (0)