방법: 관찰자 구현
관찰자 디자인 패턴은 알림에 등록하는 관찰자와 데이터를 모니터링하고 하나 이상의 관찰자에게 알림을 보내는 공급자 간에 구분이 필요합니다. 이 항목에서는 관찰자를 만드는 방법을 설명합니다. 관련 항목인 방법: 공급자 구현에서는 공급자를 만드는 방법을 설명합니다.
관찰자를 만들려면
System.IObserver<T> 인터페이스를 구현하는 형식인 관찰자를 정의합니다. 예를 들어 다음 코드에서는
Temperature
의 제네릭 형식 인수를 사용하여 구성된 System.IObserver<T> 구현인TemperatureReporter
라는 형식을 정의합니다.public class TemperatureReporter : IObserver<Temperature>
Public Class TemperatureReporter : Implements IObserver(Of Temperature)
공급자가 해당 IObserver<T>.OnCompleted 구현을 호출하기 전에 관찰자가 알림 수신을 중지할 수 있는 경우 공급자의 IObservable<T>.Subscribe 메서드에서 반환한 IDisposable 구현을 유지할 private 변수를 정의합니다. 또한 공급자의 Subscribe 메서드를 호출하고 반환된 IDisposable 개체를 저장하는 구독 메서드도 정의해야 합니다. 예를 들어 다음 코드는
unsubscriber
라는 private 변수를 정의하고, 공급자의 Subscribe 메서드를 호출하고 반환된 개체를unsubscriber
변수에 할당하는Subscribe
메서드를 정의합니다.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
예시
다음 예제에는 온도 모니터링 애플리케이션에 대한 IObserver<T> 구현을 제공하는 TemperatureReporter
클래스의 전체 소스 코드가 포함되어 있습니다.
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
참고 항목
.NET