Singleton tasarım deseni: uygulama, kod örnekleri ve ne zaman kaçınılmalı
Beceri rehberi

Singleton tasarım deseni: uygulama, kod örnekleri ve ne zaman kaçınılmalı

Hazırlayan: Mindset Institute EditörlüğüGüncellendi: 5 dk okuma

Singleton tasarım deseni adım adım: uygulama, Python ve Java kod örnekleri, çok iş parçacıklı güvenlik, dezavantajlar ve bağımlılık enjeksiyonu alternatifi.

Singleton deseni nedir?

Singleton, Gang of Four kataloğunda yaratıcı (creational) desenler arasında yer alan ve bir sınıftan uygulama boyunca yalnızca tek bir nesne üretilmesini, bu nesneye de merkezi bir erişim noktasından ulaşılmasını sağlayan tasarım desenidir. Tipik örnekler yapılandırma okuyucusu, günlük (log) yöneticisi, bağlantı havuzu ve önbellek yöneticisidir: sistemde bir tane olması anlamlı olan ve birden çok kopyası tutarsızlık yaratacak kaynaklar.

Desenin temel güvencesi şudur: nesne yalnızca bir kez oluşturulur ve herkes aynı nesneyi kullanır. Bunu sağlamak için kurucu metot dışarıya kapatılır, nesneye erişim sınıfın kendi sağladığı bir metot ya da özellik üzerinden yapılır.

Adım adım: Singleton nasıl uygulanır?

Birinci adım, ihtiyacı sınamaktır: gerçekten tek örnek mi gerekiyor, yoksa yalnızca her yerden kolay erişim mi isteniyor? İkincisi ise başka çözümler (bağımlılık enjeksiyonu) daha uygun olabilir.

İkinci adım, kurucuyu özel yapmaktır, böylece dışarıdan yeni nesne oluşturulamaz.

Üçüncü adım, sınıf içinde tek örneği tutacak statik bir alan tanımlamaktır.

Dördüncü adım, bu örneği döndüren bir erişim metodu yazmaktır; örnek henüz yoksa oluşturur, varsa aynısını döner.

Beşinci adım, çok iş parçacıklı ortamı düşünmektir: birden çok iş parçacığı aynı anda örnek yoksa ikisi de yeni bir nesne oluşturabilir. Bunu önlemek için kilit, sınıf yüklenirken erken oluşturma ya da dilin güvenli yapıları kullanılır.

Altıncı adım, test edilebilirliği planlamaktır: örnek sıfırlanabilmeli ya da arayüz üzerinden taklit edilebilmelidir.

Kod örneği: Python

Python'da en yalın ve güvenilir yaklaşım, modül düzeyinde tek nesne oluşturmaktır; modül bir kez yüklendiği için nesne de bir kez oluşur:

class Ayarlar: def __init__(self): self.degerler = {}

ayarlar = Ayarlar()

Başka bir dosyada "from ayarlar_modulu import ayarlar" ile alınan nesne her yerde aynıdır. Sınıf tabanlı bir sürüm yazmak gerekirse "__new__" metodu içinde örneği saklamak mümkündür, ancak bu yaklaşım okunabilirliği düşürür ve çoğu durumda modül düzeyi çözüm yeterlidir.

Kod örneği: Java ve çok iş parçacıklı güvenlik

Java'da güvenli ve kısa bir yol, tek öğeli bir enum kullanmaktır; bu yapı serileştirme ve yansıma saldırılarına karşı da korumalıdır:

public enum GunlukYoneticisi { ORNEK; public void yaz(String mesaj) { System.out.println(mesaj); } }

Kullanım: "GunlukYoneticisi.ORNEK.yaz(...)". Sınıf tabanlı klasik sürümde ise kurucu özel yapılır, örnek statik alanda tutulur ve erişim metodu senkronize edilir ya da örnek sınıf yüklenirken (statik başlatma) oluşturulur. Tembel oluşturma gerekiyorsa çift kontrollü kilit kullanılır; bu durumda alanın "volatile" olması şarttır. Aksi halde bir iş parçacığı yarım oluşturulmuş nesneyi görebilir.

Örneklerin amacı yaklaşımı göstermektir; gerçek projede dilin ve çatının güncel yapılarına bakılmalıdır.

Singleton'ın dezavantajları ve ne zaman kaçınılmalı

Singleton, en çok eleştirilen tasarım desenlerinden biridir ve eleştirinin gerekçeleri ciddidir: • Gizli bağımlılık: sınıflar Singleton'a doğrudan eriştiğinde bağımlılık kurucuda ya da arayüzde görünmez, kodu okumak zorlaşır. • Test zorluğu: global durum testler arasında sızar; bir test diğerinin sonucunu etkileyebilir. Taklit nesne koymak da zordur. • Tek sorumluluk ilkesinin ihlali: sınıf hem işini yapar hem de kendi örnek yaşam döngüsünü yönetir. • Çok iş parçacıklı hatalar: yanlış uygulanırsa yarış durumları ve ince hatalar doğar. • Esnekliğin kaybı: sonradan "aslında birden çok örnek gerekiyor" denirse yeniden yapılandırma zorlaşır.

Bu nedenle çoğu modern yapıda tek örnek ihtiyacı, bağımlılık enjeksiyonu kapsayıcısının "tek örnek ömrü" ayarıyla karşılanır: sınıf kendisi Singleton olmaz, ama kapsayıcı ona tek bir örnek verir. Böylece tek örnek avantajı korunur, bağımlılık görünür ve test edilebilir kalır.

Ne zaman Singleton, ne zaman alternatifi?

Karar ölçütleri: • Gerçekten sistemde yalnız bir tane olması mantıksal zorunluluksa (örneğin bir donanım kaynağına tek erişim) ve alternatif çözüm zorsa Singleton düşünülebilir. • Yalnızca kolay erişim isteniyorsa parametre olarak geçirmek ya da bağımlılık enjeksiyonu daha sağlıklıdır. • Durumsuz yardımcı işlevler için tek nesne yerine statik işlev ya da modül yeterlidir. • Test edilebilirlik öncelikse arayüz arkasında tek örnek tercih edilir.

Bir örnek senaryo: bir uygulamada ayarlar dosyası başlangıçta okunuyor. Her sınıf dosyayı yeniden okursa hem yavaş hem tutarsız olur. Çözüm, ayarları tek bir nesnede tutmak ve onu ihtiyaç duyan sınıflara kurucu üzerinden vermektir; ayarlar nesnesi uygulamada tek örnek olarak oluşturulur ama sınıflar onu global olarak çağırmaz.

Sık yapılan hatalar

  • Singleton'ı global değişken yerine kullanıp mimariyi buna bağımlı hale getirmek.
  • Çok iş parçacıklı güvenliği düşünmeden tembel oluşturma yazmak.
  • Singleton içinde değişebilir durum biriktirip testleri birbirine bağımlı hale getirmek.
  • Her yardımcı sınıfı Singleton yapmak.
  • Alt sınıflandırma gerektiren bir yapıyı Singleton ile kilitlemek.
  • Örnek yaşam döngüsünü (kapatma, temizleme) düşünmemek.

Bu beceriyi Mindset programlarında nerede çalışırsınız?

Yazılım Mimarisi ve Tasarım Desenleri programı; yazılım geliştiriciler, kıdemli mühendisler ve mimarlar için uygundur. Müfredatta SOLID ve tasarım prensipleri, yaratıcı tasarım desenleri (Singleton'ın ait olduğu grup), yapısal ve davranışsal desenler, mimari stiller, mimari değerlendirme ve refactor ile gerçek senaryo olarak kurumsal mimari tasarımı yer alır. Singleton'ı tek başına bir ezber olarak değil, diğer desenler ve tasarım ilkeleriyle birlikte karar ölçütü olarak çalışmak isteyen ekipler için bir çerçeve sunar.

İlgili Mindset programı

Yazılım Mimarisi ve Tasarım Desenleri

Sık sorulanlar

Sık sorulan sorular

Singleton deseni anti-pattern midir?

Tartışmalıdır. Aşırı ve bilinçsiz kullanıldığında global duruma bağımlılık, gizli bağımlılık ve test zorluğu yarattığı için birçok kişi bunu anti-pattern sayar. Gerçek bir tek örnek ihtiyacında ve doğru uygulandığında meşru kullanımı vardır; modern yaklaşım, tek örnek ihtiyacını sınıfa değil bağımlılık enjeksiyonu kapsayıcısına bırakmaktır.

Singleton ile statik sınıf arasındaki fark nedir?

Singleton bir nesnedir; arayüz uygulayabilir, kalıtım alabilir, tembel oluşturulabilir ve başka bir nesne ile değiştirilebilir. Statik sınıf ise nesne değildir, durumu tipe bağlıdır ve taklit edilmesi zordur. Esneklik ve test edilebilirlik gerekiyorsa Singleton ya da kapsayıcı yönetimli tek örnek tercih edilir.

Singleton çok iş parçacıklı ortamda nasıl güvenli yapılır?

Örneği sınıf yüklenirken oluşturmak (erken başlatma), erişim metodunu senkronize etmek ya da dilin sağladığı güvenli yapıları kullanmak yaygın yollardır. Tembel oluşturmada çift kontrollü kilit kullanılacaksa dilin bellek modeline dikkat edilmelidir. Mümkünse dilin standart ve güvenli çözümü tercih edilmelidir.

Singleton'ı test ederken ne yapmalı?

Singleton'ı doğrudan çağıran kodu arayüz arkasına almak ve test sırasında taklit bir uygulama enjekte etmek en temiz yoldur. Bu mümkün değilse testler arasında örneği sıfırlayan bir mekanizma sağlanmalıdır. Aksi halde bir testin bıraktığı durum sonrakini etkiler.

Her tek örnek ihtiyacında Singleton mu yazmalıyım?

Hayır. Önce bağımlılık enjeksiyonu kapsayıcısının tek örnek ömrü ayarını ya da bağımlılığı kurucudan geçirmeyi düşünün. Sınıfın kendisini Singleton yapmak, ancak bu seçenekler uygun olmadığında ve tek örnek zorunluluğu gerçekten sınıfın tanımında olmalıysa mantıklıdır.

Singleton Deseni Nasıl Uygulanır? Örnek Kod ve Tuzaklar