一起来学习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
{
    private string name;
    private List flightInfos = new List();
    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 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
{
    private List> observers;
    private List flights;
    public BaggageHandler()
    {
        observers = new List>();
        flights = new List();
    }
    public IDisposable Subscribe(IObserver 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(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();
            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 : IDisposable
{
    private List> _observers;
    private IObserver _observer;
    internal Unsubscriber(List> observers, IObserver observer)
    {
        this._observers = observers;
        this._observer = observer;
    }
    public void Dispose()
    {
        if (_observers.Contains(_observer))
            _observers.Remove(_observer);
    }
}

流程简单分析

一起来学习C#的观察者模式_第1张图片

一起来学习C#的观察者模式_第2张图片

个人理解

类:

  • 核心处理类(控制者/处理者)
    • 信息数据列表
    • 观察者列表
  • 观察者类
  • 数据信息类
  • 释放空间

流程:

处理者接收新数据判断是否存在,不存在添加到数据列表中,然后遍历观察者列表,根据新数据执行新动作。

观察者类主要实现自身的添加和删除操作,将处理者作为参数传进自身中,调用处理者中的添加观察者函数进行添加绑定。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!     

你可能感兴趣的:(一起来学习C#的观察者模式)