Observer Pattern Example in C# with IObservable

Another day, another pattern. The Observer Pattern provides a mechanism for receiving push-based notifications (like events). It separates the Subject from the Observer (separation of concerns). The original pattern by the Group of Four was implemented with base classes, but as of .NET 4 we welcome the IObserver andIObservable interfaces (both of type T) to take care of this.

So, if you want to monitor changes in, let’s say, a news feed (the subject) I can do that within an observer. This news feed pushes notifications to the observer (News Monitor) and the observer makes changes accordingly (writes something to the console). The example looks a lot like .NET event handling.

using System; using System.Collections.Generic; namespace Observer { class Program { static void Main(string[] args) { NewsFeed newsFeedNull = new NewsFeed(); NewsFeed newsFeedRemondo = new NewsFeed(); NewsFeedMonitor newsFeedMonitor = new NewsFeedMonitor(); IDisposable unsubscriberNYT = newsFeedNull.Subscribe(newsFeedMonitor); IDisposable unsubscriberRemondo = newsFeedRemondo.Subscribe(newsFeedMonitor); newsFeedNull.Uri = null; // to force an error newsFeedRemondo.Uri = new Uri("http://remondo.net/feed"); Console.Read(); unsubscriberNYT.Dispose(); unsubscriberRemondo.Dispose(); } } class NewsFeed : IObservable<NewsFeed> { private List<IObserver<NewsFeed>> observers = new List<IObserver<NewsFeed>>(); private Uri _uri; public Uri Uri { get { return _uri; } set { _uri = value; this.Notify(this); } } public IDisposable Subscribe(IObserver<NewsFeed> observer) { if (!this.observers.Contains(observer)) { observers.Add(observer); } return new Unsubscriber(this.observers, observer); } private void Notify(NewsFeed newsFeed) { foreach (var observer in this.observers) { if (this._uri == null) { observer.OnError(new Exception("Sumtinwong")); } else { observer.OnNext(this); } } } private void StopReading() { foreach (var observer in this.observers) { if (this.observers.Contains(observer)) { observer.OnCompleted(); } observers.Clear(); // No more dangling events! } } class Unsubscriber : IDisposable { private List<IObserver<NewsFeed>> _observers; private IObserver<NewsFeed> _observer; public Unsubscriber(List<IObserver<NewsFeed>> observers, IObserver<NewsFeed> observer) { this._observers = observers; this._observer = observer; } public void Dispose() { if (this._observer != null && this._observers.Contains(this._observer)) { this._observers.Remove(_observer); } } } } class NewsFeedMonitor : IObserver<NewsFeed> { public void OnCompleted() { Console.WriteLine("No more news today..."); } public void OnError(Exception error) { Console.WriteLine("Error in News Feed... " + error.Message); } public void OnNext(NewsFeed value) { Console.WriteLine("There's a news News Item... " + value.Uri.AbsoluteUri); } } }

And here’s the result (with spelling error  )…

Also check out Mattia Baldinger’s post with a nice generic IObservable class.

你可能感兴趣的:(observer)