​示例代码下载​​(根据微软官方文档示例进行分析)

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);
}
}

​流程简单分析​

C# 观察者模式_数据

C# 观察者模式_c#_02

​个人理解​

类:


  1. 核心处理类(控制者/处理者)
    信息数据列表
    观察者列表

  2. 观察者类

  3. 数据信息类

  4. 释放空间
  5. 流程:

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

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