Observer Kalıbı
Coddy'nin PHP Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 73 / 91.
Gözlemci Deseni (Observer Pattern), nesneler arasında bire-çok bir ilişki kuran davranışsal bir tasarım desenidir. Bir nesne (konu) durum değiştirdiğinde, tüm bağımlıları (gözlemciler) otomatik olarak bilgilendirilir ve güncellenir.
Bir bülten aboneliğini düşünün. Bülten öznedir ve aboneler gözlemcilerdir. Yeni bir sayı yayımlandığında, bültenin her bir abonenin ayrıntılarını bilmesine gerek kalmadan tüm aboneler bu sayıyı otomatik olarak alır.
İşte PHP'de temel bir uygulama:
<?php
interface Observer {
public function update(string $message): void;
}
class Newsletter {
private array $subscribers = [];
public function subscribe(Observer $observer): void {
$this->subscribers[] = $observer;
}
public function publish(string $content): void {
foreach ($this->subscribers as $subscriber) {
$subscriber->update($content);
}
}
}
class EmailSubscriber implements Observer {
public function __construct(private string $email) {}
public function update(string $message): void {
echo "Sending to {$this->email}: $message\n";
}
}
$newsletter = new Newsletter();
$newsletter->subscribe(new EmailSubscriber("alice@example.com"));
$newsletter->subscribe(new EmailSubscriber("bob@example.com"));
$newsletter->publish("New article released!");
Çıktı:
Sending to alice@example.com: New article released!
Sending to bob@example.com: New article released!Bu desen, subject'i (konuyu) observer'larından (gözlemcilerinden) ayırır. Newsletter sınıfının; e-posta abonelerini mi, SMS abonelerini mi yoksa anlık bildirim servislerini mi bilgilendirdiğini bilmesine gerek yoktur. Sadece Observer arayüzünü uygulayan herhangi bir yapı üzerinde update() metodunu çağırır. Bu, mevcut kodu değiştirmeden yeni gözlemci türleri eklemeyi zahmetsiz hale getirir.
Görev
KolayGözlemci Deseni'ni (Observer Pattern) kullanarak bir hisse senedi fiyat uyarı sistemi oluşturalım. Bir hisse senedinin fiyatı değiştiğinde, kayıtlı tüm yatırımcılar otomatik olarak bilgilendirilmelidir — bu, bu desenin mükemmel bir gerçek dünya uygulamasıdır.
Kodunuzu dört dosya halinde düzenleyeceksiniz:
Observer.php— Tek birupdate(string $stockName, float $price): voidmetoduna sahip birObserverarayüzü (interface) tanımlayın. Bu, tüm gözlemcilerin bildirim almak için uyması gereken sözleşmedir.Investors.php— Observer dosyasını dahil edin ve arayüzü uygulayan iki sınıf oluşturun:EmailInvestor— Yapıcısında (constructor) bir e-posta adresi alır (constructor promotion kullanın).update()metodu"Email to {$this->email}: {$stockName} is now \${$price}\n"çıktısını verir.SmsInvestor— Yapıcısında bir telefon numarası alır.update()metodu"SMS to {$this->phone}: {$stockName} is now \${$price}\n"çıktısını verir.
Stock.php— Observer dosyasını dahil edin ve konu (subject) görevi gören birStocksınıfı oluşturun. Hisse senediniz şunları yapmalıdır:- Hisse senedi adını ve mevcut fiyatını saklamalıdır (ad için constructor promotion kullanın, fiyatı
0.0olarak başlatın) - Gözlemcilerden oluşan özel (private) bir dizi tutmalıdır
- Gözlemci eklemek için bir
subscribe(Observer $observer): voidmetoduna sahip olmalıdır - Fiyatı güncelleyen ve tüm gözlemcileri bilgilendiren bir
setPrice(float $price): voidmetoduna sahip olmalıdır
update()metodunu hisse senedi adı ve yeni fiyat ile çağırın.- Hisse senedi adını ve mevcut fiyatını saklamalıdır (ad için constructor promotion kullanın, fiyatı
main.php— Investors ve Stock dosyalarını dahil edin. Üç girdi alacaksınız: bir hisse senedi adı, bir e-posta adresi ve bir telefon numarası.Verilen isimle bir
Stockoluşturun. E-posta adresiyle birEmailInvestorve telefon numarasıyla birSmsInvestorabone yapın.Tüm abonelere bildirimleri tetiklemek için hisse senedi fiyatını
150.50olarak ayarlayın.
Gözlemci Deseni, Stock sınıfınızı belirli bildirim yöntemlerinden bağımsız (decoupled) tutar. Daha sonra Stock sınıfını hiç değiştirmeden kolayca bir PushInvestor veya SlackInvestor ekleyebilirsiniz.
Kopya kağıdı
Gözlemci Deseni (Observer Pattern), bir konunun (subject) durumu değiştiğinde tüm gözlemcileri (observers) otomatik olarak bilgilendirdiği bire-çok (one-to-many) bir ilişki kurar.
Temel Bileşenler:
- Gözlemci Arayüzü (Observer Interface) —
update()metodu ile gözlemciler için sözleşmeyi tanımlar - Konu (Subject) — Gözlemcilerin bir listesini tutar ve durum değişikliklerini onlara bildirir
- Somut Gözlemciler (Concrete Observers) — Bildirimleri almak için Gözlemci arayüzünü uygularlar
Temel Uygulama:
<?php
interface Observer {
public function update(string $message): void;
}
class Subject {
private array $observers = [];
public function subscribe(Observer $observer): void {
$this->observers[] = $observer;
}
public function notify(string $data): void {
foreach ($this->observers as $observer) {
$observer->update($data);
}
}
}
class ConcreteObserver implements Observer {
public function __construct(private string $name) {}
public function update(string $message): void {
echo "Notifying {$this->name}: $message\n";
}
}
$subject = new Subject();
$subject->subscribe(new ConcreteObserver("Observer1"));
$subject->subscribe(new ConcreteObserver("Observer2"));
$subject->notify("State changed!");
Avantajlar:
- Konuyu gözlemcilerinden ayırır (decoupling)
- Mevcut kodu değiştirmeden yeni gözlemci türleri eklemek kolaydır
- Dinamik aboneliği/abonelikten çıkmayı destekler
Kendin dene
<?php
require_once 'Investors.php';
require_once 'Stock.php';
// Girdileri oku
$stockName = trim(fgets(STDIN));
$email = trim(fgets(STDIN));
$phone = trim(fgets(STDIN));
// TODO: Verilen isimle bir Stock (Hisse) oluşturun
// TODO: E-posta adresi ile bir EmailInvestor abonesi oluşturun
// TODO: Telefon numarası ile bir SmsInvestor abonesi oluşturun
// TODO: Bildirimleri tetiklemek için hisse fiyatını 150.50 olarak ayarlayın
?>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
1OOP Temelleri
Harici DosyalarOOP'ye GirişSınıflar ve Nesneler$this Anahtar KelimesiMetotlarÖzelliklerYapıcı Metot (__construct)Yıkıcı Metot (__destruct)Özet - Basit Hesap Makinesi4Kalıtım
Temel Kalıtımparent:: Anahtar KelimesiMetot Geçersiz Kılmafinal Anahtar KelimesiSoyut SınıflarÖzet - Çalışan Hiyerarşisi7Kapsülleme
Public, Protected, PrivateErişim Belirleyicilere Derinlemesine BakışGetter ve Setter MetotlarıBilgi GizlemeConstructor Promotion (8.0)Özet - Öğrenci Kayıt Sistemi10İleri Düzey OOP Kavramları
Kompozisyon vs KalıtımDependency InjectionAnonim SınıflarEnum'lar (PHP 8.1)Fiber'lar (PHP 8.1)Nesne Klonlama: Derinlemesine İncelemeGenerator'lar ve Iterator'lar13Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit KalıbıRepository Kalıbı2İsim Alanları ve Autoloading
İsim Alanlarına Girişuse Anahtar KelimesiPSR-4 Autoloading StandartıComposer AutoloaderÖzet - Düzenli Proje5Arayüzler ve Sözleşmeler
Arayüzlere GirişArayüzleri UygulamaBirden Fazla Arayüz UygulamaArayüz vs Soyut SınıfArayüzler ile Tip BelirlemeÖzet - Şekil Hesaplayıcı8Sihirli Metotlar
Sihirli Metotlara Giriş__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Nesne Klonlama__serialize & __unserializeÖzet - Özel Koleksiyon3Sınıf Özellikleri
Örnek ve Statik ÖzelliklerSınıflarda SabitlerStatik Metotlar ve ÖzelliklerPrivate ve Protected ÖzelliklerReadonly Özellikler (PHP 8.1)Özet - Banka Hesabı Yöneticisi6Çok Biçimlilik
Metot Geçersiz Kılmaya Yeniden BakışArayüzler ile Çok BiçimlilikType Hinting ve Union TypesLate Static BindingÖzet - Ödeme İşlemcisi9Trait'ler
Trait'lere GirişÇoklu Trait KullanımıTrait Çakışma ÇözümüTrait'lerde Soyut MetotlarTrait'ler ve Kalıtım12Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıObserver KalıbıStrategy Kalıbı15Final Meydan Okumaları
E-Öğrenme PlatformuBankacılık SistemiOyun Karakteri GeliştirmeAraç Kiralama Servisi