My thoughts on patterns
I’ll be honest with you…I never did like design patterns. I never got on board with it and, instead, just coded away like I thought I was supposed to do. Now, I realize they’re a bit of a necessary evil to learn, for the main reason just to be able to speak to other developers about how they did this or that. With that in mind, I thought it would be a good idea to actually start learning these things. To do that, I turn to a fairly popular book on the subject – Head First Design Patterns.
The main reason I felt I should get into design patterns is from watching a presentation from Venkat Subramaniam. After watching Design Patterns for .NET Programmers I felt like I had an epiphany on what design patterns can do and what they’re truly used for. You could say my mind was blown.
Observer Pattern
In this post I’ll describe my understanding of the Observer Pattern, mostly gained from the material presented in the book and will (attempt to) put them into my own words so others like myself can gain a further understanding of design patterns and be able to apply them to their day-to-day coding.
As the name suggests, the Observer Pattern is a pattern where the important objects are “observed” or watched for changes. A physical example of what the Observer Pattern does can be the DVD service of Netflix. You subscribe to the service and they will send you the allotted number of DVDs available. Once you unsubscribe, you no longer get a DVD.
With .NET and C# there are actually a couple of different ways to use the Observer Pattern. There’s always the classic way, using events/delegates, and the new IObservable<T> interface in the Base Class Library (BCL). Let’s briefly go through each one.
With each of these implementations I’ll try to wire up a very simple stock ticker. These will use the following Stock class:
public class Stock { public string Symbol { get; set; } public double Price { get; set; } public DateTime DateRecieved { get; set; } }
Classic
This classic version of the pattern is what is described in the Gang of Four book on design patterns. This text pretty much set the tone in what design patterns are and they go through the most notable ones. Most of the ones you’ll hear, I’m sure, are from this book.
In my example, I used interfaces, though in some implementations you may see an abstract base class being used instead. Below are the two interfaces I have for the Subject and the Observable.
public interface ISubject { void Subscribe(IObserver observer); void Unsubscribe(IObserver observer); } public interface IObserver { void Update(); }.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Pretty straight forward to see what each of these set up a contract for in each of the implementations: ISubject will Subscribe and Unsubscribe an IObserver object, which just does updates.
Let’s look at the implementation of the ISubject interface on the StockTicker class:
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(); } } }.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Not a lot that’s very interesting in here, really, until you look at the Stock property. Once this gets set to a value is when we call the Notify method that takes all of our items that have been subscribed to and updates it to our new value.
How we subscribe to notifications and the Update method is in our IObserver implementation:
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); } }.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
In the class constructor we subscribe so we will get notified of any new updates. In the Update method, we take the new values of the Stock property and, for the simplest implementation, just displaying them to the console.
And now let’s put these together in our application:
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(); }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/white-space: pre;/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Events and Delegates
If you’ve done anything with click events in .NET (in WebForms or WinForms/WPF) then you’ve messed with events (and, ultimately, the Observer Pattern).
For this, we have to set up a delegate object:
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); } }.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Keep in mind that since we created the event, the C# compiler will infer the delegate type at compile time. As you may have also noticed, I added a custom EventArgs class as well, so it will be easier for the delegate to pass the new information on.
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; } }.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
And that’s basically all there is to it for creating the event: having the delegate object created with events and, optionally, custom EventArgs that it will take. The compiler will do the rest of the work for you and all that’s left is to use it inside your app. Here’s my console application:
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(); }.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Unless the code will be reusable, I like to use lambda expressions when subscribing to an event, similar to above.
IObservable<T>
The IObservable<T> and IObserver<T> interfaces were introduced to the BCL in .NET 4 and provides another way to use the Observer Pattern.
It’s a little bit trickier to implement these interfaces since the methods on them are a bit different than what a usual interface created for the Observer Pattern may use. Also, the Subscribe method in IObservable<T> returns an IDisposable interface.
Here’s how I implemented the IObservable<T> interface. You may notice that it takes a similar approach from above when I created the ISubject interface.
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); } }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/white-space: pre;/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Just a bit different than the classical implementation. We’re still calling our own Notify method when the Stock property gets set with a new value, but within the method we’re also doing a bit of validation on the new Stock value that comes in. In our Subscribe method it does the same thing as before but instead of it returning void it now returns IDisposable. With that we created an Unsubscriber class that implements IDisposable. All we do here is pass in our list of observers and our current observer and remove it from the list whenever the Dispose method is called.
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); } } }.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Our implementation of IObserver<T> is the same as before – displaying values into the console.
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!"); } }.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
How we put it together into our application is a bit different than we’ve seen. Since the Subscribe method implements IDisposable, we can just wrap all of our code inside of a using statement. After it gets used within there, we will be unsubscribed as an observer.
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(); }
Conclusion
Hopefully, this is a decent introduction to the Observer Pattern and a couple of nice examples you can use to play around with so you can get a better understanding of it. I know I certainly did.
All the code from above can be found on GitHub.
Our Customers
Our success is determined by the strength in our relationships, level of service & customer satisfaction first in everything we do
Our Employees
Our success is determined by how well we communicate, work, support & grow together in our efforts to serve our customers.
Our Innovative Spirit
Our success is defined by seeking innovative ways to deliver value for our customers and the freedom to explore new ideas.