Menu
Coddy logo textTech

Observer-Muster (Events)

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

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

Das Muster umfasst einen Publisher, der Ereignisse auslöst, und Subscriber, die auf diese reagieren. Hier ist ein praktisches Beispiel für einen Aktienkurs-Monitor:

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 verknüpfen ihre Methoden über += mit dem Ereignis und können diese mit -= wieder trennen:

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:
// Alarm: Preis ist jetzt 150.50
// Protokolliert: 150.50

stock.PriceChanged -= logger.OnPriceChanged;  // Abmelden
stock.Price = 155.00m;
// Ausgabe: Alarm: Preis ist jetzt 155.00

Das Observer-Muster fördert eine lose Kopplung – die Stock-Klasse muss nichts über ihre Observer wissen. Neue Observer können sich anmelden, ohne den Publisher zu modifizieren, was das System einfach erweiterbar und wartbar macht.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Temperaturüberwachungssystem mithilfe des Observer-Musters mit Ereignissen. Du erstellst einen Sensor, der mehrere Beobachter benachrichtigt, sobald sich die Temperatur ändert – perfekt für Szenarien wie Klimaregelungssysteme, bei denen verschiedene Komponenten auf Temperaturaktualisierungen reagieren müssen.

Du organisierst deinen Code auf drei Dateien:

  • TemperatureSensor.cs: Erstelle eine TemperatureSensor-Klasse im Namespace Monitoring. Dies ist dein Herausgeber – das Subjekt, das von anderen Objekten beobachtet wird. Dein Sensor sollte Folgendes besitzen:
    • 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 Temperature-Eigenschaft, die das Ereignis auslöst, sobald die Temperatur auf einen neuen Wert gesetzt wird
  • Observers.cs: Erstelle zwei Beobachterklassen im selben Namespace, die sich für Temperaturänderungen registrieren:
    • DisplayUnit – verfügt über eine Methode OnTemperatureChanged(double temp), die Display: {temp}C ausgibt
    • AlarmSystem – verfügt über eine Methode OnTemperatureChanged(double temp), die Alarm Check: {temp}C ausgibt
  • Program.cs: Führe alles zusammen, indem du einen Sensor und beide Beobachter erstellst. Registriere beide Beobachter für das Ereignis des Sensors und aktualisiere anschließend die Temperatur. Danach meldest du das Alarmsystem 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:

  1. den Sensor und beide Beobachter erstellen
  2. beide Beobachter für das Ereignis TemperatureChanged registrieren
  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 sind, sollte die Ausgabe folgendermaßen aussehen:

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

Dies veranschaulicht die zentrale Stärke des Observer-Musters – der Sensor weiß nicht, wer ihm zuhört, und es ist ihm auch egal. Beobachter können sich dynamisch registrieren und abmelden, und der Herausgeber benachrichtigt einfach alle, die aktuell zuhören!

Probier es selbst

using System;
using Monitoring;

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

        // TODO: Eine TemperatureSensor-Instanz erstellen

        // TODO: DisplayUnit- und AlarmSystem-Instanzen erstellen

        // TODO: Beide Observer für das TemperatureChanged-Event registrieren

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

        // TODO: Das AlarmSystem vom Event abmelden

        // TODO: Die Temperatur des Sensors auf temp2 setzen (nur das Display 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