다음을 통해 공유


방법: 관찰자 구현

관찰자 디자인 패턴은 알림에 등록하는 관찰자와 데이터를 모니터링하고 하나 이상의 관찰자에게 알림을 보내는 공급자 간에 구분이 필요합니다. 이 항목에서는 관찰자를 만드는 방법을 설명합니다. 관련 항목인 방법: 공급자 구현에서는 공급자를 만드는 방법을 설명합니다.

관찰자를 만들려면

  1. System.IObserver<T> 인터페이스를 구현하는 형식인 관찰자를 정의합니다. 예를 들어 다음 코드에서는 Temperature의 제네릭 형식 인수를 사용하여 구성된 System.IObserver<T> 구현인 TemperatureReporter라는 형식을 정의합니다.

    public class TemperatureReporter : IObserver<Temperature>
    
    Public Class TemperatureReporter : Implements IObserver(Of Temperature)
    
  2. 공급자가 해당 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
    
  3. 이 기능이 필수인 경우 공급자가 해당 IObserver<T>.OnCompleted 구현을 호출하기 전에 관찰자가 알림 수신을 중지할 수 있게 하는 메서드를 정의합니다. 다음 예제에서는 Unsubscribe 메서드를 정의합니다.

    public virtual void Unsubscribe()
    {
       unsubscriber.Dispose();
    }
    
    Public Overridable Sub Unsubscribe()
        unsubscriber.Dispose()
    End Sub
    
  4. IObserver<T> 인터페이스로 정의된 세 가지 메서드 즉, IObserver<T>.OnNext, IObserver<T>.OnErrorIObserver<T>.OnCompleted의 구현을 지정합니다. 공급자 및 애플리케이션의 필요에 따라 OnErrorOnCompleted 메서드가 스텁 구현일 수 있습니다. 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

참고 항목