Zrozumienie mechanizmu zdarzeń (events) w C# oraz implementacja wzorca projektowego Wydawca-Subskrybent (Publisher-Subscriber). Student nauczy się definiować własne klasy argumentów zdarzeń, stosować bezpieczne wywołanie eventów oraz zarządzać subskrypcjami w celu uniknięcia wycieków pamięci.
Finał Twojego wielkiego projektu dla komisu "Auto-Premium" to inteligentny system powiadomień. Wyobraź sobie sytuację: kiedy cena konkretnego luksusowego auta ulega zmianie (np. z powodu nowej promocji lub negocjacji), inne działy firmy muszą dowiedzieć się o tym natychmiast. Biuro Sprzedaży musi zaktualizować ofertę na stronie, a Dział Marketingu wysłać newsletter do zainteresowanych klientów.
Zamiast ręcznie wywoływać metody w dziesięciu różnych klasach z poziomu obiektu samochodu (co stworzyłoby sztywny, trudny w utrzymaniu kod), wykorzystujesz zdarzenia (events). Twoja klasa "Samochod" staje się wydawcą, który po prostu "ogłasza światu" fakt zmiany ceny. Klasy "DzialSprzedazy" czy "Marketing" po prostu subskrybują to zdarzenie. Kiedy cena się zmieni, system automatycznie poinformuje wszystkich zainteresowanych. To kwintesencja luźnego powiązania (loose coupling) w architekturze oprogramowania – klasy wiedzą o sobie tylko tyle, ile jest niezbędne do współpracy. Dowiesz się również, dlaczego tak ważne jest odsubskrybowanie, gdy powiadomienia nie są już potrzebne, aby nie zaśmiecać pamięci niepotrzebnymi obiektami.
using System;
namespace LaboratoriumOOP
{
// KLASA ARGUMENTÓW: Przekazuje dane o zdarzeniu do subskrybentów.
public class CenaZmienionaEventArgs : EventArgs
{
public double StaraCena { get; }
public double NowaCena { get; }
public CenaZmienionaEventArgs(double stara, double nowa)
{
StaraCena = stara;
NowaCena = nowa;
}
}
public class Samochod
{
private double _cena;
public string Marka { get; set; }
// ZDARZENIE (Event): Oparte na standardowym delegacie EventHandler.
public event EventHandler<CenaZmienionaEventArgs> OnCenaZmieniona;
public double Cena
{
get => _cena;
set
{
if (_cena != value)
{
double stara = _cena;
_cena = value;
// Wyzwalanie zdarzenia
OnCenaZmieniona?.Invoke(this, new CenaZmienionaEventArgs(stara, value));
}
}
}
}
// SUBSKRYBENT: Klasa zainteresowana informacją o zdarzeniu.
public class BiuroSprzedazy
{
public void ReagujNaZmianeCeny(object sender, CenaZmienionaEventArgs e)
{
Samochod s = (Samochod)sender;
Console.WriteLine($"[BIURO] Cena pojazdu {s.Marka} uległa zmianie!");
Console.WriteLine($" -> Stara: {e.StaraCena} PLN, Nowa: {e.NowaCena} PLN.");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("--- ZADANIE 10: Zdarzenia i subskrypcje ---\n");
Samochod auto = new Samochod { Marka = "Tesla Model 3", Cena = 200000 };
BiuroSprzedazy biuro = new BiuroSprzedazy();
// 1. SUBSKRYPCJA (+=)
auto.OnCenaZmieniona += biuro.ReagujNaZmianeCeny;
// 2. SUBSKRYPCJA LAMBDĄ
auto.OnCenaZmieniona += (s, e) => {
Console.WriteLine("[LOGGER] Zdarzenie odnotowane w pliku logów.");
};
Console.WriteLine("Pierwsza zmiana ceny:");
auto.Cena = 185000;
// 3. ODSUBSKRYBOWANIE (-=)
// Zapobiega "wiszącym referencjom" i wyciekom pamięci.
auto.OnCenaZmieniona -= biuro.ReagujNaZmianeCeny;
Console.WriteLine("\nDruga zmiana ceny (biuro już nie obserwuje):");
auto.Cena = 170000;
Console.WriteLine("\nZakończono kompletne laboratorium OOP C#.");
Console.ReadKey();
}
}
}