옵저버 패턴 (이벤트)
Coddy C# 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 70개 중 54번째.
옵서버 패턴은 한 객체(주체)의 상태가 바뀔 때 여러 종속 객체(옵서버)에게 알리는 일대다 관계를 설정합니다. C#에서는 이벤트를 통해 이 패턴을 간결하게 구현할 수 있습니다.
이 패턴에는 이벤트를 발생시키는 게시자와 이벤트에 응답하는 구독자가 있습니다. 주가 모니터의 실제 예를 살펴보겠습니다.
public class Stock
{
private decimal _price;
public event Action<decimal> PriceChanged;
public decimal Price
{
get => _price;
set
{
_price = value;
PriceChanged?.Invoke(_price); // 모든 관찰자에게 알림
}
}
}
public class PriceAlert
{
public void OnPriceChanged(decimal newPrice)
{
Console.WriteLine($"Alert: Price is now {newPrice}");
}
}
public class PriceLogger
{
public void OnPriceChanged(decimal newPrice)
{
Console.WriteLine($"Logged: {newPrice}");
}
}구독자는 +=를 사용해 이벤트에 메서드를 연결하고, -=를 사용해 연결을 해제할 수 있습니다.
var stock = new Stock();
var alert = new PriceAlert();
var logger = new PriceLogger();
stock.PriceChanged += alert.OnPriceChanged;
stock.PriceChanged += logger.OnPriceChanged;
stock.Price = 150.50m;
// 출력:
// 알림: 현재 가격은 150.50입니다
// 기록됨: 150.50
stock.PriceChanged -= logger.OnPriceChanged; // 구독 해제
stock.Price = 155.00m;
// 출력: 알림: 현재 가격은 155.00입니다Observer 패턴은 느슨한 결합을 촉진합니다. Stock 클래스는 옵서버에 대해 아무것도 알 필요가 없습니다. 게시자를 수정하지 않고도 새 옵서버가 구독할 수 있으므로 시스템을 쉽게 확장하고 유지 관리할 수 있습니다.
챌린지
쉬움이벤트를 사용하는 Observer 패턴으로 온도 모니터링 시스템을 만들어 봅시다. 온도가 바뀔 때마다 여러 옵저버에게 알리는 센서를 만들 거예요. 이는 온도 업데이트에 여러 구성 요소가 반응해야 하는 온도 조절 시스템과 같은 상황에 안성맞춤입니다.
코드를 세 개의 파일로 나눠 작성합니다.
TemperatureSensor.cs:Monitoring네임스페이스에TemperatureSensor클래스를 만듭니다. 이 클래스는 게시자, 즉 다른 객체가 관찰하는 주체입니다. 센서에는 다음 항목이 있어야 합니다.- 현재 온도를 저장하는 private 필드
- 새 온도를 구독자에게 알리기 위해
Action<double>을 사용하는TemperatureChanged이벤트 - 온도를 새 값으로 설정할 때마다 이벤트를 발생시키는
Temperature속성
Observers.cs: 같은 네임스페이스에 온도 변화 이벤트를 구독할 옵저버 클래스 두 개를 만듭니다.DisplayUnit-OnTemperatureChanged(double temp)메서드가 있으며,Display: {temp}C를 출력합니다.AlarmSystem-OnTemperatureChanged(double temp)메서드가 있으며,Alarm Check: {temp}C를 출력합니다.
Program.cs: 센서와 두 옵저버를 만들고 함께 연결합니다. 두 옵저버 모두 센서의 이벤트를 구독하도록 한 다음 온도를 업데이트합니다. 그 후 알람 시스템의 구독을 취소하고 온도를 다시 업데이트하여 디스플레이 장치에만 알림이 전달되는 것을 확인합니다.
입력은 두 개입니다.
- 첫 번째 온도 측정값(예:
22.5) - 두 번째 온도 측정값(예:
28.0)
프로그램은 다음을 수행해야 합니다.
- 센서와 두 옵저버를 만듭니다.
- 두 옵저버 모두
TemperatureChanged이벤트를 구독하도록 합니다. - 센서의 온도를 첫 번째 입력값으로 설정합니다(두 옵저버 모두 알림을 받아야 합니다).
AlarmSystem의 이벤트 구독을 취소합니다.- 센서의 온도를 두 번째 입력값으로 설정합니다(디스플레이만 알림을 받아야 합니다).
예를 들어 입력값이 22.5와 28.0이면 출력은 다음과 같습니다.
Display: 22.5C
Alarm Check: 22.5C
Display: 28C이 예제는 Observer 패턴의 핵심적인 장점을 보여 줍니다. 센서는 누가 자신을 구독하고 있는지 알지도 못하고 신경 쓰지도 않습니다. 옵저버는 동적으로 구독하거나 구독을 취소할 수 있으며, 게시자는 현재 구독 중인 대상에게 알림을 보낼 뿐입니다!
직접 해보기
using System;
using Monitoring;
class Program
{
public static void Main(string[] args)
{
// 입력 온도를 읽습니다
double temp1 = Convert.ToDouble(Console.ReadLine());
double temp2 = Convert.ToDouble(Console.ReadLine());
// TODO: TemperatureSensor 인스턴스를 생성합니다
// TODO: DisplayUnit과 AlarmSystem 인스턴스를 생성합니다
// TODO: 두 옵저버를 TemperatureChanged 이벤트에 구독시킵니다
// TODO: 센서의 온도를 temp1로 설정합니다 (두 옵저버 모두 알림을 받음)
// TODO: AlarmSystem의 이벤트 구독을 해제합니다
// TODO: 센서의 온도를 temp2로 설정합니다 (디스플레이만 알림을 받음)
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 C# 컴파일러