操作說明:實作觀察者
觀察者設計模式需要觀察者和提供者之間的分區,其中觀察者會註冊通知,而提供者會監視資料並將通知傳送到一個或多個觀察者。 本主題討論如何建立觀察者。 相關主題如何:實作提供者會介紹如何建立提供者。
建立觀察者
定義觀察者,這是實作 System.IObserver<T> 介面的型別。 例如,下列程式碼定義名為
TemperatureReporter
的型別,它是包含Temperature
泛型型別引數的建構 System.IObserver<T> 實作。public class TemperatureReporter : IObserver<Temperature>
Public Class TemperatureReporter : Implements IObserver(Of Temperature)
如果觀察者可以在提供者呼叫其 IObserver<T>.OnCompleted 實作之前停止接收通知,請定義會保留由提供者的 IObservable<T>.Subscribe 方法傳回之 IDisposable 實作的私用變數。 您也應該定義訂閱方法,它會呼叫提供者的 Subscribe 方法並儲存傳回的 IDisposable 物件。 例如,下列的程式碼定義名為
unsubscriber
的私用變數,並定義呼叫提供者的 Subscribe 方法之Subscribe
方法,然後將傳回的物件指派到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
定義讓觀察者能夠在提供者呼叫其 IObserver<T>.OnCompleted 實作之前停止接收通知的方法 (如果需要此功能)。 下列範例定義
Unsubscribe
方法。public virtual void Unsubscribe() { unsubscriber.Dispose(); }
Public Overridable Sub Unsubscribe() unsubscriber.Dispose() End Sub
提供 IObserver<T> 介面定義的三個方法之實作:IObserver<T>.OnNext,IObserver<T>.OnError 和 IObserver<T>.OnCompleted。 視提供者和應用程式需求而定,OnError 和 OnCompleted 方法可以是虛設常式實作。 請注意,OnError 方法不應將傳遞的 Exception 物件當作例外狀況處理,而 OnCompleted 方法可以自由呼叫提供者的 IDisposable.Dispose 實作。 下列範例顯示
TemperatureReporter
類別的 IObserver<T> 實作。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
範例
以下範例包含 TemperatureReporter
類別的完整原始程式碼,它提供溫度監視應用程式的 IObserver<T> 實作。
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