The Observer design pattern in .NET, part 1
Today we’ll implement the “classic” Observer design pattern in VB .NET. This is part 1 of a 3 part series; part 2 will discuss transitioning the design pattern to .NET events, and part 3 will discuss some uses of the Observer pattern built into .NET. You can download the Observer design pattern example if you want to see the code in action.
Use the Observer design pattern when:
- You have a subject of interest whose state may be monitored.
- Any number of objects might need to monitor the subject.
- You desire “loose coupling” between the subject and the observers.
How it works
The Observer design pattern works much like a newspaper publisher and its subscribers. In fact, it is sometimes called the Publisher-Subscriber design pattern. In this pattern, you have a Subject object (the publisher) that maintains a collection of any number of observers (the subscribers). It provides methods to add and remove observers from this collection. It also contains a method to notify all observers of some change in state.
Interfaces
In the Observer pattern the publisher would be called the “subject”. The subject has state (in our case, a headline) that it maintains. The subject implements an interface as shown here:
Public Interface IObservable
Sub Subscribe(ByVal observer As IObserver)
Sub Unsubscribe(ByVal observer As IObserver)
Sub NotifySubscribers()
End Interface
It has two methods for tracking the subscription and unsubscription of subscribers, and a method for notifying subscribers of an update to the subject’s state.
In the Observer pattern the subscriber would be called the “observer”, and it implements this interface:
Public Interface IObserver
Sub Update(ByVal subject As IObservable)
End Interface
When the subject’s NotifySubscribers method is called, it calls the Update() method for every observer that is currently subscribed.
The Subject
Here is an implementation of a class we’ll call SubjectPublisher:
Public Class SubjectPublisher
Implements IObservable
Private observers As New List(Of IObserver)
Private _headline As String = ""
Public Property Headline() As String
Get
Return _headline
End Get
Set(ByVal value As String)
If _headline <> value Then
_headline = value
NotifySubscribers()
End If
End Set
End Property
Private Sub NotifySubscribers() Implements IObservable.NotifySubscribers
For Each o As IObserver In observers
o.Update(Me)
Next
End Sub
Public Sub Subscribe(ByVal observer As IObserver) Implements IObservable.Subscribe
observers.Add(observer)
End Sub
Public Sub Unsubscribe(ByVal observer As IObserver) Implements IObservable.Unsubscribe
While observers.Contains(observer)
observers.Remove(observer)
End While
End Sub
End Class
As you can see it implements the IObservable interface as discussed earlier. In addition, it implements a Headline property. Whenever the Headline changes, it calls the NotifySubscribers method to update the currently subscribed observers.
The Observer
Here is an implementation of a class we’ll call ObserverSubscriber:
Public Class ObserverSubscriber
Implements IObserver
Private _headline As String = ""
Public ReadOnly Property Headline() As String
Get
Return _headline
End Get
End Property
Public Sub Update(ByVal subject As IObservable) Implements IObserver.Update
_headline = CType(subject, SubjectPublisher).Headline
End Sub
End Class
It implements the IObserver discussed earlier. In addition, it implements a read-only Headline property in order to provide access to the value it collects during Update.
Push vs. Pull
Note that during the call to Update no specific state is sent, only a reference to the subject. We could have implemented Update so that specific state was “pushed” as a parameter. However, the preferred design pattern method is to have the observer “pull” whatever state is necessary from the subject. It could be that every observer needs different parts of the subject’s state.
Observer design pattern in action
Let’s pull the concepts together with a test GUI. Here’s a screenshot of the Observer pattern test GUI.
In this test GUI, there is a section to update the subject with a new headline, and there is a section to subscribe/unsubscribe each of three different observers. You should notice that any observer that has Subscribed? checked will receive a headline update any time the Update button is clicked for the subject. Here’s the code:
Public Class Form1
Private _subject As New SubjectPublisher
Private _observer1 As New ObserverSubscriber
Private _observer2 As New ObserverSubscriber
Private _observer3 As New ObserverSubscriber
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Private Sub uxSaveHeadline_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles uxSaveHeadline.Click
_subject.Headline = uxHeadline.Text
uxHeadline1.Text = _observer1.Headline
uxHeadline2.Text = _observer2.Headline
uxHeadline3.Text = _observer3.Headline
End Sub
Private Sub uxSubscribed1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles uxSubscribed1.CheckedChanged
If uxSubscribed1.Checked Then
_subject.Subscribe(_observer1)
Else
_subject.Unsubscribe(_observer1)
End If
End Sub
Private Sub uxSubscribed2_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles uxSubscribed2.CheckedChanged
If uxSubscribed2.Checked Then
_subject.Subscribe(_observer2)
Else
_subject.Unsubscribe(_observer2)
End If
End Sub
Private Sub uxSubscribed3_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles uxSubscribed3.CheckedChanged
If uxSubscribed3.Checked Then
_subject.Subscribe(_observer3)
Else
_subject.Unsubscribe(_observer3)
End If
End Sub
End Class
That’s it for today. Don’t forget to check in later when we talk about the use of .NET events in the observer pattern, and occurrences of the observer pattern built into .NET.







[...] is part 2 in a series about the Observer design pattern in .NET. In part one, we saw how to implement the pattern using the “classical” approach. In this part, [...]