Gereksinimler ve Ön Hazırlık
Bu rehberdeki uygulamaları gerçekleştirmek için sisteminizde Java Development Kit (JDK) 17 veya üzeri bir sürümün yüklü olması önerilir. 2026 yılı standartlarında, Java'nın sunduğu modern arayüz (interface) ve lambda ifadeleri ile bu yapıyı oldukça kısa ve okunabilir bir şekilde kuracağız.
- JDK 17+ (LTS sürüm olması kararlılık için önemlidir).
- IDE: IntelliJ IDEA veya Eclipse (Modern Java desteği olan herhangi bir IDE).
- Maven veya Gradle (Bağımlılık yönetimi için önerilir ancak bu örnekte saf Java kullanılacaktır).
Observer Arayüzünün Tanımlanması
İlk adım olarak, gözlemci nesnelerimizin ortak bir kontrata sahip olmasını sağlayacak arayüzü oluşturmalıyız. Bu arayüz, özne tarafından tetiklendiğinde çalışacak olan metodu tanımlar.
public interface Observer {
void update(String message);
}
Burada tanımladığımız update metodu, özne (Subject) tarafından bir olay gerçekleştiğinde çağrılacaktır. Bu arayüz sayesinde, farklı türdeki gözlemcileri (örneğin; E-posta servisi, Log servisi) aynı yapı üzerinden yönetebiliriz.
Subject (Özne) Sınıfının Oluşturulması
Özne sınıfı, gözlemcileri listesinde tutan ve olay gerçekleştiğinde bu listeyi dolaşarak bildirim yapan sınıftır. Bu sınıfın gözlemcileri ekleme, çıkarma ve bilgilendirme yetenekleri olmalıdır.
import java.util.ArrayList;
import java.util.List;
public class EventManager {
private List observers = new ArrayList();
public void subscribe(Observer observer) {
observers.add(observer);
}
public void unsubscribe(Observer observer) {
observers.remove(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
EventManager sınıfı, List yapısını kullanarak gözlemcileri bellekte tutar. notifyObservers metodu, bir döngü aracılığıyla kayıtlı tüm gözlemcilerin update metodunu tetikler.
Somut Gözlemci Sınıflarının Uygulanması
Şimdi Observer arayüzünü implemente eden somut sınıflarımızı oluşturalım. Bu sınıflar, bildirim geldiğinde kendi iş mantıklarını yürüteceklerdir.
public class EmailNotification implements Observer {
@Override
public void update(String message) {
System.out.println("E-posta gönderiliyor: " + message);
}
}
public class LoggingService implements Observer {
@Override
public void update(String message) {
System.out.println("Log dosyasına yazılıyor: " + message);
}
}
Bu yapıda, EmailNotification ve LoggingService sınıfları birbirinden bağımsızdır. Her ikisi de aynı olaydan haberdar olur ancak kendi görevlerine odaklanırlar.
Olay Yönetimini Test Etme
Tüm parçaları bir araya getirerek sistemin nasıl çalıştığını gözlemleyelim. Bir Main sınıfı oluşturarak gözlemcileri kaydedelim ve olayı tetikleyelim.
public class Main {
public static void main(String[] args) {
EventManager manager = new EventManager();
Observer email = new EmailNotification();
Observer logger = new LoggingService();
manager.subscribe(email);
manager.subscribe(logger);
manager.notifyObservers("Sistem başlatıldı!");
}
}
Kod çalıştırıldığında, hem e-posta hem de loglama servisinin aynı anda "Sistem başlatıldı!" mesajını işlediğini göreceksiniz. Bu, Observer deseninin gücünü gösterir.
Observer Tasarım Kalıbı Karşılaştırma Tablosu
| Özellik | Observer Deseni | Doğrudan Çağrı |
|---|---|---|
| Bağımlılık | Düşük (Loose Coupling) | Yüksek (Tight Coupling) |
| Esneklik | Yüksek (Yeni gözlemci kolay eklenir) | Düşük (Kod değişikliği gerektirir) |
| Karmaşıklık | Orta | Düşük |
Güvenlik Uyarısı: Observer desenini kullanırken, gözlemcilerin birbirini beklemediğinden emin olun. Eğer bir gözlemci çok yavaş çalışıyorsa, ana akışın (main thread) kilitlenmemesi için asenkron (eşzamansız) yapıları veya Java'nın
CompletableFuturesınıfını kullanmayı değerlendirin.
Sıkça Sorulan Sorular
Observer deseni neden kullanılır?
Nesneler arasındaki bağımlılığı azaltmak ve sistemin genişletilebilirliğini artırmak için kullanılır. Bir nesne değiştiğinde, onu kullanan diğer nesneleri tek tek güncellemek yerine, bu desen sayesinde otomatik bildirim sağlanır.
Java'daki Observer sınıfı neden deprecated (kullanımdan kaldırıldı)?
Java'nın eski java.util.Observer ve java.util.Observable sınıfları, çoklu kalıtım kısıtlamaları ve thread-safety (iş parçacığı güvenliği) sorunları nedeniyle Java 9 itibarıyla deprecated edilmiştir. Bu yüzden kendi arayüzümüzü yazmak en güvenli yoldur.
Gözlemciler arasında veri paylaşımı nasıl yapılır?
Gözlemciler arasında doğrudan veri paylaşımı yerine, update metoduna bir DTO (Data Transfer Object) parametresi göndererek verinin tüm gözlemcilere tutarlı bir şekilde iletilmesini sağlayabilirsiniz.
Bu yapı çoklu iş parçacığında (multithreading) güvenli midir?
Yukarıdaki basit örnek thread-safe değildir. Eğer aynı anda birden fazla iş parçacığı gözlemci ekleyip çıkaracaksa, List yerine CopyOnWriteArrayList kullanmanız önerilir.
Observer deseni ile Event Listener arasındaki fark nedir?
Aslında Observer deseni, Event Listener yapısının temelini oluşturur. Event Listener, bu desenin daha spesifik ve genellikle UI (kullanıcı arayüzü) bileşenleri için özelleştirilmiş halidir.
Observer Deseninde Performans Optimizasyonu ve Bellek Yönetimi
Observer tasarım kalıbı, özellikle çok sayıda gözlemcinin (observer) sisteme dahil olduğu durumlarda bellek sızıntılarına (memory leak) yol açabilir. Bir gözlemci, özneye (subject) kayıtlı olduğu sürece, çöp toplayıcı (Garbage Collector) tarafından temizlenemez. Bu durumu engellemek için WeakReference yapısını kullanmak kritik bir öneme sahiptir.
Zayıf Referanslar ile Bellek Sızıntılarını Önleme
Gözlemcilerinizi doğrudan bir ArrayList içerisinde tutmak yerine, onları WeakReference ile sarmalayarak öznenin gözlemcileri "zayıf" bir şekilde tutmasını sağlayabilirsiniz. Böylece, gözlemci nesnesi başka bir yerde kullanılmadığında, özne onu otomatik olarak serbest bırakabilir.
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
public class WeakSubject {
private List observers = new ArrayList();
public void attach(Observer observer) {
observers.add(new WeakReference(observer));
}
public void notifyObservers(String event) {
for (WeakReference ref : observers) {
Observer obs = ref.get();
if (obs != null) {
obs.update(event);
}
}
// Temizlik işlemi: null olan referansları listeden kaldır
observers.removeIf(ref -> ref.get() == null);
}
}
Observer Deseninde Hata Ayıklama (Debugging) Stratejileri
Observer deseninde olay akışını takip etmek, kodun dağıtık yapısı nedeniyle bazen karmaşık olabilir. Hata ayıklama sürecini kolaylaştırmak için şu yöntemleri izleyebilirsiniz:
- Olay Günlüğü (Event Logging): Her bildirim gönderildiğinde bir log mekanizması kullanarak hangi gözlemcinin hangi veriyi aldığını kayıt altına alın.
- StackTrace Analizi: Bildirim zincirinin nerede koptuğunu anlamak için
Thread.currentThread().getStackTrace()metodunu kullanarak tetikleyici kaynağı belirleyin. - Gözlemci İsimlendirme: Her gözlemciye benzersiz bir kimlik veya isim vererek, loglarda hangi nesnenin işlem yaptığını kolayca ayırt edin.
Profesyonel İpucu: Eğer uygulamanızda çok fazla olay tetikleniyorsa, gözlemcilerin update() metodunda ağır işlemler yapmaktan kaçının. Bu tür işlemleri ayrı bir ExecutorService üzerinde asenkron olarak çalıştırmak, ana uygulamanızın donmasını engeller.
Asenkron Bildirim Mekanizması
Bildirimlerin senkron yapılması, gözlemcilerden birinin hata alması durumunda tüm zinciri durdurabilir. Bunu aşmak için bildirimleri bir kuyruk yapısı üzerinden yönetebilirsiniz:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class AsyncSubject {
private final ExecutorService executor = Executors.newFixedThreadPool(4);
public void notifyObservers(String event) {
for (Observer obs : observers) {
executor.submit(() -> obs.update(event));
}
}
}
Sonuç
Java ile Observer tasarım kalıbı kullanarak olay yönetimi yapmak, özellikle kurumsal çaplı projelerde kodunuzun bakımını kolaylaştırır. Bu makalede adım adım öğrendiğiniz yapı, nesne yönelimli programlamanın temel taşlarından biridir. Bir sonraki aşamada, bu yapıyı java.util.concurrent paketindeki araçlarla birleştirerek asenkron olay yönetimi üzerine çalışmanızı öneririm. Kodunuzun temiz ve sürdürülebilir kalması için bu tür tasarım kalıplarını projelerinizde uygulamaktan çekinmeyin.


Yorumlar (0)
Yorum Yaz