jwood803
1/15/2014 - 10:29 PM

Observer pattern implementations in .NET

Observer pattern implementations in .NET

public class Unsubscriber : IDisposable
{
  private readonly List<IObserver<Stock>> _observers;
  private readonly IObserver<Stock> _observer;

  public Unsubscriber(List<IObserver<Stock>> observers, IObserver<Stock> observer)
  {
    _observers = observers;
    _observer = observer;
  }

  public void Dispose()
  {
    if (_observer != null && _observers.Contains(_observer))
    {
      _observers.Remove(_observer);
    }
  }
}
public class StockTickerObservable : IObservable<Stock>
{
  private readonly List<IObserver<Stock>> _observers;
  private Stock _stock;

  public StockTickerObservable()
  {
    _observers = new List<IObserver<Stock>>();
  }

  public Stock Stock
  {
    get { return _stock; }
    set
    {
      _stock = value;
      this.Notify();
    }
  }

  private void Notify()
  {
    _observers.ForEach(i =>
    {
      if (_stock.Price < 0 || _stock.DateRecieved == DateTime.MinValue)
      {
        i.OnError(new ApplicationException("Invalid stock information"));
      }
      else
      {
        i.OnNext(_stock);
      }
    });
  }

  public IDisposable Subscribe(IObserver<Stock> observer)
  {
    if (!_observers.Contains(observer))
    {
        _observers.Add(observer);
    }

    return new Unsubscriber(_observers, observer);
  }
}
public class TwitterStockObservable : IObserver<Stock>
{
  public void OnNext(Stock value)
  {
    Console.WriteLine("{0} changed with price {1}. Recieved on {2}", value.Symbol, value.Price, value.DateRecieved);
  }

  public void OnError(Exception error)
  {
    Console.WriteLine("An error occured: {0}", error.Message);
  }

  public void OnCompleted()
  {
    Console.WriteLine("Completed!");
  }
}
static void Main(string[] args)
{
  // Create the Stock Ticker subject object
  var stockTickerObservable = new StockTickerObservable();

  // Create the object to observe
  var twitterStockObservable = new TwitterStockObservable();

  // Subscribe and check for new notifications. This will dispose
  // of the object (release the observable) once finished.
  using (stockTickerObservable.Subscribe(twitterStockObservable))
  {
      stockTickerObservable.Stock = new Stock
                                      {
                                          Symbol = "TWTR",
                                          Price = 5000,
                                          DateRecieved = DateTime.Now
                                      };
  }

  Console.ReadLine();
}
static void Main(string[] args)
{
  // Create a reference to the delegate object
  var stockTickerDelegate = new StockTickerDelegate();
  
  // Subscribe to the StockTicker event. Using a lambda expression to give the 
  // event what happens after it has been triggered.
  stockTickerDelegate.StockTicker += (s, e) => 
      Console.WriteLine("Stock from event. Symbol {0}, price {1}, date recieved {2}",
          e.Symbol, e.Price, e.DateRecieved);

  // An event has been triggered...
  stockTickerDelegate.SetStock(new Stock { Symbol = "TWTR", Price = 500, DateRecieved = DateTime.Now });

  Console.ReadLine();
}
public class StockTickerDelegate
{
  public event EventHandler<StockTickerEventArgs> StockTicker;
  
  protected virtual void OnNewStock(string symbol, double price, DateTime dateRecieved)
  {
      if (StockTicker != null)
      {
          StockTicker(this, new StockTickerEventArgs(symbol, price, dateRecieved));
      }
  }
  
  public void SetStock(Stock stock)
  {
      OnNewStock(stock.Symbol, stock.Price, stock.DateRecieved);
  }
}
public class StockTickerEventArgs : EventArgs
{
  public StockTickerEventArgs(string symbol, double price, DateTime dateRecieved)
  {
    this.Symbol = symbol;
    this.Price = price;
    this.DateRecieved = dateRecieved;
  }
  
  public DateTime DateRecieved { get; set; }
  public double Price { get; set; }
  public string Symbol { get; set; }
}
public class StockTicker : ISubject
{
  private readonly List<IObserver> _observers;
  private Stock _stock;
  
  public StockTicker()
  {
    _observers = new List<IObserver>();
  }
  
  public void Subscribe(IObserver observer)
  {
    _observers.Add(observer);
  }
  
  public void Unsubscribe(IObserver observer)
  {
    if (_observers.Contains(observer))
    {
        _observers.Remove(observer);
    }
  }
  
  public void Notify()
  {
    _observers.ForEach(i => i.Update());
  }
  
  public Stock Stock
  {
    get { return _stock; }
    set
    {
        _stock = value;
        this.Notify();
    }
  }
}
public class TwitterStock : IObserver
{
  private StockTicker _stockData;
  private double _price;
  private DateTime _dateRecieved;
  private string _symbol;

  public TwitterStock(StockTicker stockData)
  {
    _stockData = stockData;
    _stockData.Subscribe(this);
  }

  public void Update()
  {
    _symbol = _stockData.Stock.Symbol;
    _price = _stockData.Stock.Price;
    _dateRecieved = _stockData.Stock.DateRecieved;

    Display();
  }

  private void Display()
  {
    Console.WriteLine("{0} changed with price {1} on {2}.", _symbol, _price, _dateRecieved);
  }
}
static void Main(string[] args)
{
  // Monitor when specific events occur and react to them
  var stockTicker = new StockTicker();
  
  // Create observers, subscribe, and listen for the events of the stock ticker
  var twitterStock = new TwitterStock(stockTicker);
  
  // Setting the "Stock" property will trigger a new update and will display to the console.
  stockTicker.Stock = new Stock
                      {
                          Symbol = "TWTR",
                          Price = 1000,
                          DateRecieved = DateTime.Now
                      };
  
  Console.ReadLine();
}
public interface ISubject
{
  void Subscribe(IObserver observer);
  void Unsubscribe(IObserver observer);
}
public interface IObserver
{
  void Update();
}
public class Stock
{
  public string Symbol { get; set; }
  public double Price { get; set; }
  public DateTime DateRecieved { get; set; }
}