Singleton Design Pattern

Yunus Emre Ulusan
4 min readDec 23, 2023

--

Singleton Design Pattern, yazılım geliştirme sürecinde kullanılan bir tasarım örüntüsüdür. Bu örüntü, bir sınıfın yalnızca bir örneğinin oluşturulmasını ve bu örneğe genel olarak erişimi sağlar. Bu örneğe global bir erişim noktası oluşturulur ve bu sayede bu örneğe her yerden kolayca erişilebilir.

Genellikle Singleton Design Pattern şu durumlarda kullanılır:

Tek Bir Kaynak Yönetimi: Örneğin, bir veritabanı bağlantısı veya dosya işlemleri gibi kaynakları paylaşmanın gerektiği durumlarda kullanılabilir. Birden fazla örneğin aynı kaynağa erişmesi istenmiyorsa Singleton kullanılabilir.

Global Erişim Noktası: Sistem genelinde tek bir noktadan erişilmesi gereken durumlarda tercih edilir. Örneğin, bir log yöneticisi veya yapılandırma ayarları gibi.

Sınırlı Kaynak Kullanımı: Sınırlı kaynakların olduğu durumlarda (örneğin bellek) ve bu kaynakların tekrar tekrar oluşturulması yerine bir kez oluşturularak kullanılması gereken durumlarda kullanışlıdır.

Gerçek hayattan bir örnek vermek gerekirse,

Bir otomobil üreticisi fabrikası düşünelim. Bu fabrikada sadece bir adet CEO (Chief Executive Officer — İcra Kurulu Başkanı) bulunabilir. Yani, fabrikanın CEO’su yalnızca bir tane olabilir. Bu durumda CEO, Singleton örneğine benzetilebilir. Tüm çalışanlar CEO’ya erişebilir, ancak sadece bir tane CEO örneği vardır ve bu örnek fabrikanın genelinde erişilebilirdir.

Diğer bir örnek ise bir banka yazılımı düşünelim. Banka sisteminde genellikle bir tane hesap yöneticisi bulunur. Bu hesap yöneticisi, tüm hesapların yönetiminden sorumlu olan ve banka işlemlerini denetleyen bir kişidir. Banka sistemi içerisinde sadece bir tane hesap yöneticisi bulunmalıdır ve bu yöneticiye her yerden erişilebilir olmalıdır. Bu durumda, hesap yöneticisi Singleton olarak tasarlanabilir.

Sektörel bir örnek vermek gerekirse,

Yazılımın bir parçası olan veritabanı bağlantı yöneticisi de Singleton olarak tasarlanabilir. Bir uygulama genelinde tek bir veritabanı bağlantısı oluşturulması ve bu bağlantının her yerden erişilebilir olması gerekebilir. Bu durumda Singleton Design Pattern kullanılarak bir veritabanı bağlantısı yöneticisi tasarlanabilir.,

Örnek kodumuzu aşağıda inceleyelim;

public class Singleton {
// Örneğin tutulacağı private static değişken
private static Singleton instance;
private String databaseUrl;

// Constructor private yapılarak dışarıdan yeni bir örnek oluşturulması engellenir
private Singleton() {
// Örnek bir başlangıç değeri atayalım
databaseUrl = "jdbc:mysql://localhost:3306/mydatabase";
}

// Tek bir örnek döndüren metot
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}

public String getDatabaseUrl() {
return databaseUrl;
}

public void setDatabaseUrl(String url) {
this.databaseUrl = url;
}

public void connectToDatabase() {
// Veritabanına bağlanmak için gerekli işlemler
System.out.println("Veritabanına bağlanılıyor: " + databaseUrl);
// Bağlantı işlemleri...
System.out.println("Veritabanına bağlantı başarılı!");
}


}

Bu yukardaki örneğe ek olarak gerçek hayatta sıkça kullandığımız ödeme sistemini ele alabiliriz. Bu Singleton yapısını kullanarak bir ödeme sistemini ele alabiliriz. Ödeme sistemlerinde genellikle bir ödeme geçidi kullanılır ve bu geçide sadece bir tane erişim noktası olmalıdır. Bu durumda, ödeme geçidi Singleton olarak tasarlanabilir. connectToPaymentGateway() gibi bir metot bu geçide bağlanmak için kullanılabilir ve ödeme işlemleri bu tek örnek üzerinden yönetilebilir.

Bu örneğe ek destek olarak aşağıdaki kodu inceleyelim.

public class Singleton {
private static Singleton instance;
private String paymentGatewayUrl;

private Singleton() {
// Örnek bir başlangıç değeri atayalım
paymentGatewayUrl = "https://payment.gateway.com";
}

public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}

public String getPaymentGatewayUrl() {
return paymentGatewayUrl;
}

public void setPaymentGatewayUrl(String url) {
this.paymentGatewayUrl = url;
}

public void connectToPaymentGateway() {
// Ödeme geçidine bağlanmak için gerekli işlemler
System.out.println("Ödeme geçidine bağlanılıyor: " + paymentGatewayUrl);
// Bağlantı işlemleri...
System.out.println("Ödeme geçidine bağlantı başarılı!");
}

}

Bu örnek Singleton sınıfına eklenmiş bir paymentGatewayUrl değişkeni ve connectToPaymentGateway() adında bir metot içeriyor. Bu metot, ödeme geçidine bağlanmak için kullanılabilir.

public class PaymentProcessor {
public static void main(String[] args) {
// Singleton örneğini al
Singleton paymentGateway = Singleton.getInstance();

// Ödeme geçidine bağlan
paymentGateway.connectToPaymentGateway();

// Ödeme geçidi URL'sini değiştir
paymentGateway.setPaymentGatewayUrl("https://new.payment.gateway.com");

// Yeni URL ile tekrar bağlan
paymentGateway.connectToPaymentGateway();
}
}

Bu kod örneği, Singleton sınıfından getInstance() metodu ile bir örnek alıyor ve bu örneği kullanarak ödeme geçidine iki kez bağlanıyor. İlk bağlantıda varsayılan URL kullanılırken, daha sonra setPaymentGatewayUrl() metoduyla URL değiştirilerek tekrar bağlantı kuruluyor. Bu sayede tek bir örnek üzerinde ödeme geçidi bağlantısının nasıl yönetilebileceği gösteriliyor.

Singleton Design Pattern, özellikle çoklu thread’lerin olduğu ortamlarda dikkatlice kullanılmalıdır. Çünkü birden fazla thread aynı anda getInstance() metodunu çağırırsa ve henüz örnek oluşturulmamışsa, birden fazla örnek oluşturulabilir ve bu istenmeyen sonuçlara yol açabilir. Bu durumda senkronizasyon veya farklı implementasyonlar kullanılarak çoklu thread sorunları çözülebilir.

Yukarıda verilen örnekler ve kodlar, Singleton Pattern’in nasıl kullanılabileceğini ve hangi durumlarda faydalı olabileceğini anlatmaya çalıştım. Ancak, dikkat edilmesi gereken noktalar da var:

  • Thread Güvenliği: Eğer uygulamanızda çoklu thread kullanılıyorsa Singleton pattern’i thread güvenli bir şekilde uygulamak önemlidir. Birden fazla thread aynı anda getInstance() metodunu çağırabilir ve bu durumda birden fazla örnek oluşturulabilir. Bu sorunu çözmek için senkronizasyon veya farklı yöntemler kullanılabilir.
  • Test Edilebilirlik: Singleton pattern, test edilmesi zor olabilir. Kodunuzu test etmek istediğinizde Singleton kullanımı bazen zorluklar çıkarabilir. Bağımlılık enjeksiyonu gibi farklı tasarım yöntemleri bu konuda yardımcı olabilir.

Genel olarak, Singleton pattern ihtiyaç duyulan durumlarda kullanıldığında faydalı olabilir, ancak doğru senaryoda ve dikkatli bir şekilde uygulanmalıdır. Bu sayede kodunuz daha düzenli ve yönetilebilir olabilir.

Bu yazıda Singleton pattern’in ne olduğunu, nasıl kullanıldığını ve hangi durumlarda faydalı olduğunu inceledik. Tasarımın karmaşıklığını azaltırken, kodun daha modüler ve erişilebilir olmasını sağlayabilir. Tekrarlı örneklerin oluşturulmasını engelleyerek kaynak kullanımını optimize edebilirsiniz. Umarım Singleton pattern hakkındaki bu yazı, yazılım geliştirme süreçlerinizde faydalı olur.

Kaynak :

1- Design Patterns Book

--

--