Menu
Coddy logo textTech

Observer Kalıbı (Olaylar)

Coddy'nin C# Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 54 / 70.

Observer deseni, bir nesnenin (konu) durumu değiştiğinde birden fazla bağımlı nesneyi (gözlemciler) bilgilendirdiği bire-çok bir ilişki kurar. C#'ta olaylar (events), bu deseni zarif bir şekilde uygulamak için yerleşik bir yol sağlar.

Bu desen, olayları tetikleyen bir yayıncıyı ve bunlara yanıt veren aboneleri içerir. İşte bir hisse senedi fiyat monitörüne dair pratik bir örnek:

public class Stock
{
    private decimal _price;
    
    public event Action<decimal> PriceChanged;
    
    public decimal Price
    {
        get => _price;
        set
        {
            _price = value;
            PriceChanged?.Invoke(_price);  // Tüm gözlemcileri bilgilendir
        }
    }
}

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

Aboneler, metotlarını += kullanarak olaya bağlarlar ve -= ile ayırabilirler:

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

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

stock.Price = 150.50m;
// Çıktı:
// Uyarı: Fiyat artık 150.50
// Günlüğe kaydedildi: 150.50

stock.PriceChanged -= logger.OnPriceChanged;  // Abonelikten ayrıl
stock.Price = 155.00m;
// Çıktı: Uyarı: Fiyat artık 155.00

Observer deseni gevşek bağlılığı teşvik eder - Stock sınıfının gözlemcileri hakkında hiçbir şey bilmesine gerek yoktur. Yeni gözlemciler, yayıncıyı değiştirmeden abone olabilir, bu da sistemi genişletmeyi ve bakımını yapmayı kolaylaştırır.

challenge icon

Görev

Kolay

Olayları (events) kullanarak Gözlemci (Observer) desenini temel alan bir sıcaklık izleme sistemi oluşturalım. Sıcaklık her değiştiğinde birden fazla gözlemciyi bilgilendiren bir sensör oluşturacaksınız; bu, farklı bileşenlerin sıcaklık güncellemelerine tepki vermesi gereken iklimlendirme sistemleri gibi senaryolar için mükemmeldir.

Kodunuzu üç dosya halinde düzenleyeceksiniz:

  • TemperatureSensor.cs: Monitoring ad alanında (namespace) bir TemperatureSensor sınıfı oluşturun. Bu sizin yayıncınızdır (publisher) - diğer nesnelerin gözlemleyeceği konu. Sensörünüz şunlara sahip olmalıdır:
    • Mevcut sıcaklığı saklamak için özel (private) bir alan
    • Aboneleri yeni sıcaklık hakkında bilgilendirmek için Action<double> kullanan TemperatureChanged adlı bir olay (event)
    • Sıcaklık her yeni bir değere ayarlandığında olayı tetikleyen bir Temperature özelliği (property)
  • Observers.cs: Aynı ad alanında sıcaklık değişikliklerine abone olacak iki gözlemci sınıfı oluşturun:
    • DisplayUnit - Display: {temp}C yazdıran bir OnTemperatureChanged(double temp) metoduna sahiptir
    • AlarmSystem - Alarm Check: {temp}C yazdıran bir OnTemperatureChanged(double temp) metoduna sahiptir
  • Program.cs: Bir sensör ve her iki gözlemciyi oluşturarak her şeyi bir araya getirin. Her iki gözlemciyi de sensörün olayına abone yapın, ardından sıcaklığı güncelleyin. Bundan sonra, alarm sisteminin aboneliğini iptal edin ve sadece ekran ünitesinin bildirimi aldığını göstermek için sıcaklığı tekrar güncelleyin.

İki girdi alacaksınız:

  • İlk sıcaklık okuması (örneğin, 22.5)
  • İkinci sıcaklık okuması (örneğin, 28.0)

Programınız şunları yapmalıdır:

  1. Sensörü ve her iki gözlemciyi oluşturun
  2. Her iki gözlemciyi TemperatureChanged olayına abone yapın
  3. Sensörün sıcaklığını ilk girdi değerine ayarlayın (her iki gözlemci de bilgilendirilmelidir)
  4. AlarmSystem'ın olay aboneliğini iptal edin
  5. Sensörün sıcaklığını ikinci girdi değerine ayarlayın (sadece ekran bilgilendirilmelidir)

Örneğin, girdiler 22.5 ve 28.0 ise, çıktı şöyle olmalıdır:

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

Bu, Gözlemci deseninin temel gücünü gösterir - sensör kendisini kimin dinlediğini bilmez veya umursamaz. Gözlemciler dinamik olarak abone olabilir ve abonelikten çıkabilir ve yayıncı sadece o anda kim dinliyorsa onu bilgilendirir!

Kopya kağıdı

Gözlemci (Observer) deseni, bir nesnenin (konu) durumu değiştiğinde birden fazla bağımlı nesneyi (gözlemciler) bilgilendirdiği bire-çok bir ilişki kurar.

C#'ta olaylar (events), bu deseni uygulamak için yerleşik bir yol sunar. Desen, olayları tetikleyen bir yayıncı (publisher) ve bunlara yanıt veren aboneleri (subscribers) içerir.

Temel Olay Uygulaması

event Action<T> kullanarak bir olay tanımlayın ve durum değiştiğinde bunu çağırın:

public class Stock
{
    private decimal _price;
    
    public event Action<decimal> PriceChanged;
    
    public decimal Price
    {
        get => _price;
        set
        {
            _price = value;
            PriceChanged?.Invoke(_price);  // Tüm gözlemcileri bilgilendir
        }
    }
}

Gözlemcileri Oluşturma

Gözlemciler, olay imzasıyla eşleşen yöntemlere sahip sınıflardır:

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

Abone Olma ve Abonelikten Ayrılma

Olaylara abone olmak için += ve abonelikten ayrılmak için -= kullanın:

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

stock.PriceChanged += alert.OnPriceChanged;    // Abone ol
stock.PriceChanged += logger.OnPriceChanged;   // Abone ol

stock.Price = 150.50m;  // Her iki gözlemci de bilgilendirilir

stock.PriceChanged -= logger.OnPriceChanged;   // Abonelikten ayrıl

stock.Price = 155.00m;  // Sadece alert bilgilendirilir

Gözlemci deseni gevşek bağlılığı (loose coupling) teşvik eder - yayıncının gözlemcileri hakkında hiçbir şey bilmesine gerek yoktur. Yeni gözlemciler, yayıncıyı değiştirmeden abone olabilirler.

Kendin dene

using System;
using Monitoring;

class Program
{
    public static void Main(string[] args)
    {
        // Giriş sıcaklıklarını oku
        double temp1 = Convert.ToDouble(Console.ReadLine());
        double temp2 = Convert.ToDouble(Console.ReadLine());

        // YAPILACAK: Bir TemperatureSensor örneği oluşturun

        // YAPILACAK: DisplayUnit ve AlarmSystem örneklerini oluşturun

        // YAPILACAK: Her iki gözlemciyi de TemperatureChanged olayına abone yapın

        // YAPILACAK: Sensörün sıcaklığını temp1 olarak ayarlayın (her iki gözlemciye de bildirim gider)

        // YAPILACAK: AlarmSystem'in olay aboneliğini iptal edin

        // YAPILACAK: Sensörün sıcaklığını temp2 olarak ayarlayın (yalnızca ekran birimine bildirim gider)
    }
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler