Источник – MSDN по .NET Framework 4.5
В следующем примере шаблон разработки наблюдателя используется для реализации информационной системы выдачи багажа в аэропорту. Класс BaggageInfo предоставляет информацию о прибывающих рейсах и лентах, с которых можно получить багаж с каждого рейса. Он показан в следующем примере.
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 { et { return this.origin; }
}
public int Carousel { get { return this.location; }
}
}
Класс BaggageHandler отвечает за получение информации о прибывающих рейсах и лентах выдачи багажа. На внутреннем уровне он поддерживает две коллекции.
· observers - коллекция клиентов, которые будут получать обновленную информацию.
· flights - коллекция рейсов и соответствующих им лент.
Обе коллекции представлены универсальными объектами List<T>, экземпляры которых создаются в конструкторе класса BaggageHandler. В следующем примере показан исходный код для класса BaggageHandler.
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();
}
}
Клиенты, желающие получать обновленную информацию, вызывают метод BaggageInfo.Subscribe. Если клиент ранее не подписался на уведомления, ссылка на реализацию IObserver<T> клиента добавляется в коллекцию observers.
Перегруженный метод BaggageHandler.BaggageStatus может быть вызван для указания того, что багаж с определенного рейса либо выгружается, либо более не выгружается. В первом случае методу передается номер рейса, аэропорт отправления рейса и лента, на которую выгружается багаж. Во втором случае методу передается только номер рейса. Для выгружаемого багажа метод проверяет, существует ли переданная методу информация BaggageInfo в коллекции flights. Если информация не существует, метод добавляет эту информацию и вызывает метод OnNext каждого наблюдателя. В отношении рейсов, багаж которых более не выгружается, метод проверяет, хранится ли информация по этому рейсу в коллекции flights. Если информация хранится, этот метод вызывает метод OnNext каждого наблюдателя и удаляет объект BaggageInfo из коллекции flights.
После посадки последнего рейса текущего дня и обработки его багажа вызывается метод BaggageHandler.LastBaggageClaimed. Этот метод вызывает метод OnCompleted каждого наблюдателя для указания того, что все уведомления завершены, а затем очищает коллекцию observers.
Метод Subscribe поставщика возвращает реализацию IDisposable, позволяющую наблюдателям прекратить получение уведомлений до вызова метода OnCompleted. В следующем примере показан исходный код для этого класса Unsubscriber(Of BaggageInfo). Когда в методе BaggageHandler.Subscribe создается экземпляр этого класса, ему передается ссылка на коллекцию observers и ссылка на наблюдатель, добавленный в эту коллекцию. Эти ссылки назначаются локальным переменным. Когда вызывается метод Dispose объекта, он проверяет, существует ли еще наблюдатель в коллекции observers, и, если это так, удаляет наблюдатель.
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);
}
}
В следующем примере приводится реализация IObserver<T> с именем ArrivalsMonitor, которая является базовым классом, отображающим информацию о выдаче багажа. Информация отображается в алфавитном порядке по названию города
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.