Vorgehensweise: Implementieren eines Observers
Das Entwurfsmuster „Observer“ erfordert eine Trennung zwischen einem Observer, der für den Empfang von Benachrichtigungen registriert wird, und einem Anbieter, der Daten überwacht und Benachrichtigungen an mindestens einen Observer sendet. In diesem Thema wird das Erstellen eines Observers behandelt. In dem verwandten Thema Vorgehensweise: Implementieren eines Anbieters wird erläutert, wie ein Anbieter erstellt wird.
So erstellen Sie einen Observer
Definieren Sie den Observer, der einen Typ zur Implementierung der System.IObserver<T>-Schnittstelle aufweist. Der folgende Code definiert z.B. einen Typ namens
TemperatureReporter
, der eine erstellte System.IObserver<T>-Implementierung mit einem generischen Typargument vonTemperature
darstellt.public class TemperatureReporter : IObserver<Temperature>
Public Class TemperatureReporter : Implements IObserver(Of Temperature)
Wenn der Observer den Empfang von Benachrichtigungen beenden kann, bevor der Anbieter seine IObserver<T>.OnCompleted-Implementierung aufruft, definieren Sie eine private Variable, die die von der IObservable<T>.Subscribe-Methode des Anbieters zurückgegebene IDisposable-Implementierung enthalten soll. Sie sollten auch eine Abonnementmethode definieren, die die Subscribe-Methode des Anbieters aufruft und das zurückgegebene IDisposable-Objekt speichert. Der folgende Code definiert z.B. eine private Variable mit dem Namen
unsubscriber
und definiert eineSubscribe
-Methode, die die Subscribe-Methode des Anbieters aufruft und das zurückgegebene Objekt derunsubscriber
-Variable zuweist.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
Wenn dieses Feature erforderlich sein sollte, definieren Sie eine Methode, die dem Observer das Beenden des Benachrichtigungsempfangs ermöglicht, bevor der Anbieter die jeweilige IObserver<T>.OnCompleted-Implementierung aufruft. Im folgenden Beispiel wird eine
Unsubscribe
-Methode definiert.public virtual void Unsubscribe() { unsubscriber.Dispose(); }
Public Overridable Sub Unsubscribe() unsubscriber.Dispose() End Sub
Stellen Sie Implementierungen der drei durch die IObserver<T>-Schnittstelle definierten Methoden bereit: IObserver<T>.OnNext, IObserver<T>.OnError, und IObserver<T>.OnCompleted. Je nach Anbieter und den Anforderungen der Anwendung, kann es sich bei der OnError- und OnCompleted-Methode um Stubimplementierungen handeln. Hinweis: Die OnError-Methode sollte das übergebene Exception-Objekt nicht als Ausnahme behandeln, und die OnCompleted-Methode kann nach Bedarf die IDisposable.Dispose-Implementierung des Anbieters aufrufen. Im folgenden Beispiel wird die
TemperatureReporter
-Implementierung der IObserver<T>-Klasse veranschaulicht.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
Beispiel
Das folgende Beispiel enthält den vollständigen Quellcode für die TemperatureReporter
-Klasse, um die IObserver<T>-Implementierung für eine Anwendung zur Temperaturüberwachung zu definieren.
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