Comment : implémenter une méthode Observer

Le modèle de design observateur requiert une division entre un observateur, qui s’inscrit pour recevoir des notifications, et un fournisseur, qui surveille les données et envie des notifications à un ou plusieurs observateurs. Cette rubrique décrit comment créer un observateur. Une rubrique connexe, Guide pratique pour implémenter un fournisseur, explique comment créer un fournisseur.

Pour créer un observateur

  1. Définissez l’observateur, qui est un type qui implémente l’interface System.IObserver<T>. Par exemple, le code suivant définit un type intitulé TemperatureReporter, qui est une implémentation System.IObserver<T> construite avec un argument de type générique Temperature.

    public class TemperatureReporter : IObserver<Temperature>
    
    Public Class TemperatureReporter : Implements IObserver(Of Temperature)
    
  2. Si l’observateur peut cesser de recevoir des notifications avant que le fournisseur appelle son implémentation IObserver<T>.OnCompleted, définissez une variable privée qui contiendra l’implémentation IDisposable retournée par la méthode IObservable<T>.Subscribe du fournisseur. Vous devez également définir une méthode d’abonnement qui appelle la méthode Subscribe du fournisseur et stocke l’objet IDisposable retourné. Par exemple, le code suivant définit une variable privée nommée unsubscriber et une méthode Subscribe qui appelle la méthode Subscribe du fournisseur, puis affecte l’objet retourné à la variable unsubscriber.

    public class TemperatureReporter : IObserver<Temperature>
    {
       private IDisposable unsubscriber;
       private bool first = true;
       private Temperature last;
    
       public virtual void Subscribe(IObservable<Temperature> provider)
       {
          unsubscriber = provider.Subscribe(this);
       }
    
    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. Définissez une méthode qui permet à l’observateur de cesser de recevoir des notifications avant que le fournisseur appelle son implémentation IObserver<T>.OnCompleted, si cette fonctionnalité est nécessaire. L'exemple suivant définit une méthode Unsubscribe.

    public virtual void Unsubscribe()
    {
       unsubscriber.Dispose();
    }
    
    Public Overridable Sub Unsubscribe()
        unsubscriber.Dispose()
    End Sub
    
  4. Fournissez des implémentations des trois méthodes définies par l’interface IObserver<T> : IObserver<T>.OnNext, IObserver<T>.OnError et IObserver<T>.OnCompleted. Selon le fournisseur et les besoins de l’application, les méthodes OnError et OnCompleted peuvent être des implémentations de type stub. Notez que la méthode OnError ne doit pas gérer l’objet Exception transmis en tant qu’exception, et la méthode OnCompleted est libre d’appeler l’implémentation IDisposable.Dispose du fournisseur. L’exemple suivant illustre l’implémentation IObserver<T> de la classe TemperatureReporter.

    public virtual void OnCompleted()
    {
       Console.WriteLine("Additional temperature data will not be transmitted.");
    }
    
    public virtual void OnError(Exception error)
    {
       // Do nothing.
    }
    
    public virtual void OnNext(Temperature value)
    {
       Console.WriteLine("The temperature is {0}°C at {1:g}", value.Degrees, value.Date);
       if (first)
       {
          last = value;
          first = false;
       }
       else
       {
          Console.WriteLine("   Change: {0}° in {1:g}", value.Degrees - last.Degrees,
                                                        value.Date.ToUniversalTime() - last.Date.ToUniversalTime());
       }
    }
    
    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
    

Exemple

L’exemple suivant contient le code source complet de la classe TemperatureReporter, qui fournit l’implémentation IObserver<T> pour une application de surveillance de la température.

public class TemperatureReporter : IObserver<Temperature>
{
   private IDisposable unsubscriber;
   private bool first = true;
   private Temperature last;

   public virtual void Subscribe(IObservable<Temperature> provider)
   {
      unsubscriber = provider.Subscribe(this);
   }

   public virtual void Unsubscribe()
   {
      unsubscriber.Dispose();
   }

   public virtual void OnCompleted()
   {
      Console.WriteLine("Additional temperature data will not be transmitted.");
   }

   public virtual void OnError(Exception error)
   {
      // Do nothing.
   }

   public virtual void OnNext(Temperature value)
   {
      Console.WriteLine("The temperature is {0}°C at {1:g}", value.Degrees, value.Date);
      if (first)
      {
         last = value;
         first = false;
      }
      else
      {
         Console.WriteLine("   Change: {0}° in {1:g}", value.Degrees - last.Degrees,
                                                       value.Date.ToUniversalTime() - last.Date.ToUniversalTime());
      }
   }
}
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

Voir aussi