Singleton Kalıbı
Coddy'nin Java Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 65 / 87.
Singleton Deseni, bir sınıfın uygulamanız boyunca yalnızca bir örneğe sahip olmasını sağlayan ve bu örneğe küresel bir erişim noktası sunan bir oluşturucu (creational) tasarım desenidir. Bu, yapılandırma yöneticileri, bağlantı havuzları veya günlükleme (logging) servisleri gibi paylaşılması gereken kaynaklar için kullanışlıdır.
Bu desen, yapıcıyı (constructor) private yaparak çalışır ve doğrudan örneklemeyi engeller. Bunun yerine, statik bir metot tek örneğe erişimi kontrol eder:
public class DatabaseConnection {
private static DatabaseConnection instance;
// Özel yapıcı (constructor) doğrudan örneklemeyi engeller
private DatabaseConnection() {
System.out.println("Connection created");
}
// Global erişim noktası
public static DatabaseConnection getInstance() {
if (instance == null) {
instance = new DatabaseConnection();
}
return instance;
}
public void query(String sql) {
System.out.println("Executing: " + sql);
}
}getInstance() fonksiyonuna yapılan her çağrı aynı nesneyi döndürür. Örnek, yalnızca ilk kez istendiğinde oluşturulur; buna lazy initialization (tembel başlatma) denir:
DatabaseConnection db1 = DatabaseConnection.getInstance();
DatabaseConnection db2 = DatabaseConnection.getInstance();
System.out.println(db1 == db2); // true - aynı örnekBir Singleton'ın temel bileşenleri şunlardır: örneği tutan bir private static alan, bir private yapıcı (constructor) ve örneği döndüren bir public static metot. Bu kombinasyon, nesneyi kaç kez isterseniz isteyin, her zaman aynı nesneyi almanızı garanti eder.
Görev
KolaySingleton Desenini kullanarak bir uygulama için yapılandırma yöneticisi oluşturalım! Yapılandırma yöneticiniz, uygulamanızın tüm bölümlerinin, erişim talebi kaç kez yapılırsa yapılsın aynı ayarları paylaşmasını sağlayacaktır.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
AppConfig.java: Uygulama yapılandırma ayarlarını yöneten bir Singleton sınıfı oluşturun.AppConfigsınıfınız şunlara sahip olmalıdır:Tek örneği tutmak için private static bir alan.
appNameadında private bir String alanı vemaxUsersadında private bir int alanı.appNamedeğerini"MyApplication"vemaxUsersdeğerini100olarak başlatan, ardındanAppConfig initializedyazdıran private bir yapıcı (constructor).Örneği yalnızca henüz mevcut değilse oluşturan (lazy initialization) ve ardından onu döndüren public static bir
getInstance()metodu.Uygulama adını güncelleyen bir
setAppName(String name)metodu.Maksimum kullanıcı sayısını güncelleyen bir
setMaxUsers(int max)metodu.App: [appName], Max Users: [maxUsers]yazdıran birdisplaySettings()metodu.Main.java: Singleton yapınızın doğru çalıştığını gösterin! İki girdi alacaksınız: yeni bir uygulama adı (String) ve yeni bir maksimum kullanıcı değeri (tamsayı).Öncelikle,
AppConfigsınıfından bir örnek alın ve bunuconfig1adlı bir değişkende saklayın. Varsayılan değerleri göstermek içindisplaySettings()metodunu çağırın.Ardından,
config1üzerindesetAppNamevesetMaxUsersmetodlarını çağırarak girdi değerlerinizi kullanarak ayarları güncelleyin.Başka bir örnek alın ve bunu
config2içinde saklayın.config1üzerinden yapılan değişikliklerin yansıtıldığını kanıtlamak içinconfig2üzerindedisplaySettings()metodunu çağırın.Son olarak,
config1 == config2karşılaştırmasını yaparak her iki referansın da aynı nesneyi işaret edip etmediğini yazdırın:Same instance: [true/false].
Sırasıyla iki girdi alacaksınız: yeni uygulama adı (String) ve yeni maksimum kullanıcı sayısı (tamsayı).
Bu meydan okuma, Singleton Deseninin temel faydasını göstermektedir: Yapılandırmayı kaç kez isterseniz isteyin, her zaman aynı paylaşılan duruma sahip aynı örneği alırsınız!
Kopya kağıdı
Singleton Deseni (Singleton Pattern), bir sınıfın uygulama boyunca yalnızca bir örneğe sahip olmasını sağlayarak bu örneğe küresel bir erişim noktası sunar.
Temel Bileşenler:
- Tek örneği tutan bir
private staticalan - Doğrudan örneklemeyi önlemek için bir
privateyapıcı (constructor) - Örneği döndüren bir
public staticmetot
Temel Uygulama:
public class DatabaseConnection {
private static DatabaseConnection instance;
// Özel yapıcı doğrudan örneklemeyi önler
private DatabaseConnection() {
System.out.println("Connection created");
}
// Küresel erişim noktası
public static DatabaseConnection getInstance() {
if (instance == null) {
instance = new DatabaseConnection();
}
return instance;
}
public void query(String sql) {
System.out.println("Executing: " + sql);
}
}Kullanım:
DatabaseConnection db1 = DatabaseConnection.getInstance();
DatabaseConnection db2 = DatabaseConnection.getInstance();
System.out.println(db1 == db2); // true - aynı örnekÖrnek yalnızca ilk kez istendiğinde oluşturulur; buna geç yükleme (lazy initialization) denir. getInstance() yöntemine yapılan her çağrı aynı nesneyi döndürerek uygulama genelinde paylaşılan bir durum sağlar.
Kendin dene
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Girdileri oku
String newAppName = scanner.nextLine();
int newMaxUsers = scanner.nextInt();
// TODO: AppConfig'in ilk örneğini al ve config1 içinde sakla
// TODO: Varsayılan değerleri göstermek için config1 üzerinde displaySettings() metodunu çağır
// TODO: config1 üzerinde setAppName ve setMaxUsers kullanarak ayarları güncelle
// TODO: Başka bir örnek al ve config2 içinde sakla
// TODO: Değişikliklerin paylaşıldığını kanıtlamak için config2 üzerinde displaySettings() metodunu çağır
// TODO: Her iki referansın da aynı nesneyi işaret edip etmediğini yazdır:
// config1 == config2 kullanarak "Same instance: [true/false]"
}
}
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 Nesnelerthis Anahtar KelimesiMetotlarAlanlar (Öznitelikler)Yapıcı MetotYapıcı Metot Aşırı YüklemeÖzet - Basit Hesap Makinesi4Kalıtım
Temel Kalıtım (extends)super Anahtar KelimesiMetot Geçersiz Kılma (@Override)Yapıcı Metot ZincirlemeObject SınıfıTekli ve Çok Seviyeli KalıtımNeden Çoklu Sınıf Kalıtımı Yok?Özet - Çalışan Hiyerarşisi7Özel Metotlar ve Object Sınıfı
toString() Metoduequals() ve hashCode()clone() MetoducompareTo() ve ComparableComparator ArayüzüÖzet - Özel Sıralama2Erişim Belirleyiciler ve Kapsülleme
Erişim Seviyelerine Genel BakışGetter ve Setter MetotlarıBilgi Gizlemefinal Anahtar KelimesiÖzet - Banka Hesabı Yöneticisi5Polimorfizm
Metot Aşırı Yükleme TemelleriMetot Geçersiz Kılma (Çalışma Zamanı)Upcasting ve Downcastinginstanceof OperatörüSoyut Sınıflar ve MetotlarÖzet - Şekil Hesaplayıcı8İleri Düzey OOP Kavramları
Kompozisyon vs KalıtımAgregasyon vs KompozisyonDahili, Yuvalanmış ve Anonim SınıflarEnum'lar ve Enum MetotlarıRecords (Java 16+)Sealed Classes (Java 17+)11Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıBuilder KalıbıObserver KalıbıStrategy Kalıbı14Final Meydan Okumaları
E-Öğrenme PlatformuBankacılık SistemiOyun Karakteri GeliştirmeAraç Kiralama Servisi3Sınıf Özellikleri ve Statik Üyeler
Instance ve Statik DeğişkenlerStatik MetotlarStatik BloklarSabitler (static final)Özet - Sayaç ve Utility6Arayüzler ve Soyut Sınıflar
Arayüzlere GirişArayüzleri UygulamaÇoklu Arayüz UygulamaArayüzlerde Default ve StaticSoyut Sınıflar ve ArayüzlerFonksiyonel ArayüzlerÖzet - Ödeme Sistemi9Generics
Generics'e GirişGeneric SınıflarGeneric MetotlarSınırlandırılmış Tip ParametreleriWildcard'lar (?, extends, super)Özet - Generic Container12Tasarı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ıYineleyici Kalıbı