zoukankan      html  css  js  c++  java
  • C#订阅与发布标准实现

    大概看了下C#官方提供的IObservable接口以及IObserver接口来实现发布和订阅,写的很标准,很有代表性,做下笔记,以后要是项目需要用到发布订阅再基于自己的需求改:

    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; }
       }
    }
    
    ///
    /// 发布者
    ///
    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();
       }
    }
    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);
       }
    }
    
    ///
    /// 订阅者
    ///
    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)
       {
          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 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);
            provider.BaggageStatus(712);
            observer2.Unsubscribe();
            
            provider.BaggageStatus(400);
            provider.LastBaggageClaimed();
        }
    }
    View Code
  • 相关阅读:
    kickstart自动安装部署RHEL7
    物流即使查询API
    快递单号查询快递鸟API接口-100家快递单轨迹推送
    物流跟踪API-快递单订阅
    如何最快实现物流即使查询功能-物流轨迹查询API
    提供一个不错的物流物流接口给大家,本人亲测,真的不错
    给idea添加类注释和方法注释模板
    分享一个生成反遗忘复习计划的java程序
    用TreeSet和Comparator给list集合元素去重
    对poi-excel导出的浅层理解
  • 原文地址:https://www.cnblogs.com/zhiyong-ITNote/p/10121600.html
Copyright © 2011-2022 走看看