The Observer Pattern in C#
There are a few ways to implement this pattern and I will show you two different ways to do it, but first things first.
The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically. - Head First, Design Patterns
When you are working with this pattern you usually have something called a Subject (sometimes referred to as Observerable) and an Observer. The Subject is an object that messages the Observers when its state is changed, just like it says in the above definition.
To illustrate how the pattern works you should think of a newspaper subscription, there you (the observer) subscribe to a newspaper (the subject) which you will receive when ever they send out a new issue.
In the first example we will look at how this pattern can be applied with a few interfaces and in the second example we will use a delegate and an event.
When this pattern is implemented in the right way you will have a loosely coupled design, which of course is something we want.
Example 1 – Using interfaces
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | public interface ISubject { void RegisterObserver(IObserver o); void RemoveObserver(IObserver o); void NotifyObservers(); } public interface IObserver { void Update(string story); } public class NewsPublisher : ISubject { private List<IObserver> observers = new List<IObserver>(); private List<string> archive = new List<string>(); public void RegisterObserver(IObserver o) { observers.Add(o); } public void RemoveObserver(IObserver o) { observers.Remove(o); } public void NotifyObservers() { foreach(IObserver o in observers) { o.Update(archive[archive.Count - 1]); } } public void PublishBreakingNews(string story) { archive.Add(story); ArchiveChanged(); } private void ArchiveChanged() { NotifyObservers(); } } public class NewsSubscriber : IObserver { public void Update(string story) { Console.WriteLine("--------------------- Breaking News ---------------------"); Console.Write(story); Console.WriteLine(); } } class Program { static void Main(string[] args) { NewsSubscriber me = new NewsSubscriber(); NewsPublisher publisher = new NewsPublisher(); publisher.RegisterObserver(me); publisher.PublishBreakingNews("hello world"); } } |
Example 2 – Using delegates and events
This example look a lot like the Event Pattern, but there are a few conventions that differs like the name convention but also how the signature of the method looks like for the delegate, but since we aren’t using that pattern let’s move on.
I have added a few comments here and there to show the similarities between the previous example and this one.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | /// <summary> /// Observer /// </summary> public class NewsSubscriber { public void Update(string story) { Console.WriteLine("--------------------- Breaking News ---------------------"); Console.Write(story); Console.WriteLine(); } } /// <summary> /// Subject /// </summary> public class NewsPublisher { private readonly List<string> archive = new List<string>(); public delegate void NotifyObserversHandler(string story); public event NotifyObserversHandler ArchiveChanged; public void PublishBreakingNews(string story) { archive.Add(story); // Notify observers ArchiveChanged(archive[archive.Count - 1]); } } class Program { static void Main(string[] args) { NewsSubscriber me = new NewsSubscriber(); NewsPublisher publisher = new NewsPublisher(); //add the delegate to the event (register observer) publisher.ArchiveChanged += me.Update; publisher.PublishBreakingNews("Hello world"); } } |
Finale word
As you can see the two examples work pretty much the same way, so it is really up to you to choose which one you prefer.
Further reading
[...] Read more: Fat Agnus [...]
The Observer Pattern in C#…
DotNetBurner - burning hot .net content…