How to: Implement an Observer

.NET Framework (current version)
 

The observer design pattern requires a division between an observer, which registers for notifications, and a provider, which monitors data and sends notifications to one or more observers. This topic discusses how to create an observer. A related topic, How to: Implement a Provider, discusses how to create an provider.

To create an observer

  1. Define the observer, which is a type that implements the System.IObserver<T> interface. For example, the following code defines a type named TemperatureReporter that is a constructed System.IObserver<T> implementation with a generic type argument of Temperature.

    Public Class TemperatureReporter : Implements IObserver(Of Temperature)
    

  2. If the observer can stop receiving notifications before the provider calls its IObserver<T>.OnCompleted implementation, define a private variable that will hold the IDisposable implementation returned by the provider's IObservable<T>.Subscribe method. You should also define a subscription method that calls the provider's Subscribe method and stores the returned IDisposable object. For example, the following code defines a private variable named unsubscriber and defines a Subscribe method that calls the provider's Subscribe method and assigns the returned object to the unsubscriber variable.

    Public Class TemperatureReporter : Implements IObserver(Of Temperature)
    
       Private unsubscriber As IDisposable
       Private first As Boolean = True
       Private last As Temperature
    
       Public Overridable Sub Subscribe(ByVal provider As IObservable(Of Temperature))
          unsubscriber = provider.Subscribe(Me)
       End Sub
    

  3. Define a method that enables the observer to stop receiving notifications before the provider calls its IObserver<T>.OnCompleted implementation, if this feature is required. The following example defines an Unsubscribe method.

       Public Overridable Sub Unsubscribe()
          unsubscriber.Dispose()
       End Sub
    

  4. Provide implementations of the three methods defined by the IObserver<T> interface: IObserver<T>.OnNext, IObserver<T>.OnError, and IObserver<T>.OnCompleted. Depending on the provider and the needs of the application, the OnError and OnCompleted methods can be stub implementations. Note that the OnError method should not handle the passed Exception object as an exception, and the OnCompleted method is free to call the provider's IDisposable.Dispose implementation. The following example shows the IObserver<T> implementation of the TemperatureReporter class.

       Public Overridable Sub OnCompleted() Implements System.IObserver(Of Temperature).OnCompleted
          Console.WriteLine("Additional temperature data will not be transmitted.")
       End Sub
    
       Public Overridable Sub OnError(ByVal [error] As System.Exception) Implements System.IObserver(Of Temperature).OnError
          ' Do nothing.
       End Sub
    
       Public Overridable Sub OnNext(ByVal value As Temperature) Implements System.IObserver(Of Temperature).OnNext
          Console.WriteLine("The temperature is {0}°C at {1:g}", value.Degrees, value.Date)
          If first Then
             last = value
             first = False
          Else
             Console.WriteLine("   Change: {0}° in {1:g}", value.Degrees - last.Degrees,
                                                           value.Date.ToUniversalTime - last.Date.ToUniversalTime)
          End If
       End Sub
    

The following example contains the complete source code for the TemperatureReporter class, which provides the IObserver<T> implementation for a temperature monitoring application.

Public Class TemperatureReporter : Implements IObserver(Of Temperature)

   Private unsubscriber As IDisposable
   Private first As Boolean = True
   Private last As Temperature

   Public Overridable Sub Subscribe(ByVal provider As IObservable(Of Temperature))
      unsubscriber = provider.Subscribe(Me)
   End Sub

   Public Overridable Sub Unsubscribe()
      unsubscriber.Dispose()
   End Sub

   Public Overridable Sub OnCompleted() Implements System.IObserver(Of Temperature).OnCompleted
      Console.WriteLine("Additional temperature data will not be transmitted.")
   End Sub

   Public Overridable Sub OnError(ByVal [error] As System.Exception) Implements System.IObserver(Of Temperature).OnError
      ' Do nothing.
   End Sub

   Public Overridable Sub OnNext(ByVal value As Temperature) Implements System.IObserver(Of Temperature).OnNext
      Console.WriteLine("The temperature is {0}°C at {1:g}", value.Degrees, value.Date)
      If first Then
         last = value
         first = False
      Else
         Console.WriteLine("   Change: {0}° in {1:g}", value.Degrees - last.Degrees,
                                                       value.Date.ToUniversalTime - last.Date.ToUniversalTime)
      End If
   End Sub
End Class

IObserver<T>
Observer Design Pattern
How to: Implement a Provider
Observer Design Pattern Best Practices

Show: