Menu
CoddyTech

Observer-Muster (Events)

Teil des Abschnitts Objektorientierte Programmierung der C#-Journey von Coddy. Lektion 54 von 70.

Das Beobachtermuster stellt eine Eins-zu-viele-Beziehung her, bei der ein Objekt (das Subjekt) mehrere abhängige Objekte (Beobachter) benachrichtigt, wenn sich sein Zustand ändert. In C# bieten Ereignisse eine integrierte Möglichkeit, dieses Muster elegant umzusetzen.

Das Muster umfasst einen Herausgeber, der Ereignisse auslöst, und Abonnenten, die darauf reagieren. Hier ist ein praktisches Beispiel für eine Überwachung von Aktienkursen:

public class Stock
{
    private decimal _price;
    
    public event Action<decimal> PriceChanged;
    
    public decimal Price
    {
        get => _price;
        set
        {
            _price = value;
            PriceChanged?.Invoke(_price);  // Alle Beobachter benachrichtigen
        }
    }
}

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}");
    }
}

Abonnenten hängen ihre Methoden mit += an das Ereignis an und können sie mit -= wieder entfernen:

var stock = new Stock();
var alert = new PriceAlert();
var logger = new PriceLogger();

stock.PriceChanged += alert.OnPriceChanged;
stock.PriceChanged += logger.OnPriceChanged;

stock.Price = 150.50m;
// Ausgabe:
// Warnung: Price beträgt jetzt 150.50
// Protokolliert: 150.50

stock.PriceChanged -= logger.OnPriceChanged;  // Abmelden
stock.Price = 155.00m;
// Ausgabe: Warnung: Price beträgt jetzt 155.00

Das Observer-Muster fördert eine lose Kopplung – die Klasse Stock muss nichts über ihre Beobachter wissen. Neue Beobachter können sich anmelden, ohne den Herausgeber zu ändern, sodass sich das System leicht erweitern und warten lässt.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Temperaturüberwachungssystem mit dem Beobachtermuster und Ereignissen. Du erstellst einen Sensor, der mehrere Beobachter benachrichtigt, sobald sich die Temperatur ändert – ideal für Szenarien wie Klimaregelungssysteme, in denen verschiedene Komponenten auf Temperaturänderungen reagieren müssen.

Du organisierst deinen Code auf drei Dateien:

  • TemperatureSensor.cs: Erstelle eine Klasse TemperatureSensor im Namespace Monitoring. Das ist dein Herausgeber – das Subjekt, das andere Objekte beobachten. Dein Sensor sollte Folgendes haben:
    • Ein privates Feld zum Speichern der aktuellen Temperatur
    • Ein Ereignis namens TemperatureChanged, das Action<double> verwendet, um Abonnenten über die neue Temperatur zu benachrichtigen
    • Eine Eigenschaft Temperature, die das Ereignis auslöst, sobald die Temperatur auf einen neuen Wert gesetzt wird
  • Observers.cs: Erstelle zwei Beobachterklassen im selben Namespace, die Temperaturänderungen abonnieren:
    • DisplayUnit – hat eine Methode OnTemperatureChanged(double temp), die Display: {temp}C ausgibt
    • AlarmSystem – hat eine Methode OnTemperatureChanged(double temp), die Alarm Check: {temp}C ausgibt
  • Program.cs: Füge alles zusammen, indem du einen Sensor und beide Beobachter erstellst. Abonniere mit beiden Beobachtern das Ereignis des Sensors und aktualisiere dann die Temperatur. Danach meldest du das Alarmsystem vom Ereignis ab und aktualisierst die Temperatur erneut, um zu zeigen, dass nur die Anzeigeeinheit die Benachrichtigung erhält.

Du erhältst zwei Eingaben:

  • Erster Temperaturmesswert (z. B. 22.5)
  • Zweiter Temperaturmesswert (z. B. 28.0)

Dein Programm sollte Folgendes tun:

  1. Den Sensor und beide Beobachter erstellen
  2. Beide Beobachter beim Ereignis TemperatureChanged abonnieren
  3. Die Temperatur des Sensors auf den ersten Eingabewert setzen (beide Beobachter sollten benachrichtigt werden)
  4. AlarmSystem vom Ereignis abmelden
  5. Die Temperatur des Sensors auf den zweiten Eingabewert setzen (nur die Anzeige sollte benachrichtigt werden)

Wenn die Eingaben beispielsweise 22.5 und 28.0 lauten, sollte die Ausgabe wie folgt aussehen:

Display: 22.5C
Alarm Check: 22.5C
Display: 28C

Das zeigt die zentrale Stärke des Beobachtermusters: Der Sensor weiß nicht und muss sich nicht darum kümmern, wer ihm zuhört. Beobachter können sich jederzeit anmelden und abmelden, und der Herausgeber benachrichtigt einfach diejenigen, die gerade zuhören!

Probier es selbst

using System;
using Monitoring;

class Program
{
    public static void Main(string[] args)
    {
        // Eingabetemperaturen einlesen
        double temp1 = Convert.ToDouble(Console.ReadLine());
        double temp2 = Convert.ToDouble(Console.ReadLine());

        // TODO: Eine TemperatureSensor-Instanz erstellen

        // TODO: Instanzen von DisplayUnit und AlarmSystem erstellen

        // TODO: Beide Beobachter für das TemperatureChanged-Ereignis registrieren

        // TODO: Die Temperatur des Sensors auf temp1 setzen (beide Beobachter werden benachrichtigt)

        // TODO: AlarmSystem vom Ereignis abmelden

        // TODO: Die Temperatur des Sensors auf temp2 setzen (nur DisplayUnit wird benachrichtigt)
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-C#-Compiler