Online Pazarlama Bloğu

Singleton Tasarım Deseni

September 13, 2018 • ☕️ 3 dk okuma • 🏷

Yazar tarafından şu dillere çevrildi: English

Singleton, tasarım desenleri arasındaki en basit modellerden birisidir ve yaratıcı tasarım desenleri arasında yer almaktadır. Singleton ile sistem içerisinde bir sınıfın yalnızca bir tane nesnesinin oluşturulabilmesi garanti altına alınmaktadır.

Bazı durumlar da bir sınıfın yalnızca tek bir örneği işlemlerimizi gerçekleştirmemiz için yeterlidir. Örneğin, veri tabanı bağlansını gerçekleştiren bir sınıfımız olduğunu düşünelim. Bu sınıfımızı kullanmak isteyecek birden fazla nesnemiz olabilir/olacaktır. Böyle bir durumda her nesnenin bu sınıfı kullanmak için ayrı ayrı birden fazla veritabanı bağlantı nesnesi üretmeleri maliyetli ve gereksiz olacaktır. Bu durumun önüne geçmek için sistemde veritabanı sınıfından tek bir tane nesne üretilmesini ve veritabanı sınıfına ihtiyaç duyan nesnelerin bu nesneye erişmelerini sağlayacak bir sınıf işimizi görecektir.

Bu tasarım deseni kullanılarak, sistem içerisindeki genel değişkenler ya da değeri değişmeyen değişkenler tek bir nesnede toplanabilir. Sistem içerisinde tek nesne yaratılabilmesi yordamlar ve statik değişkenler yardımıyla gerçekleştirilebilir.


Yöntem 1. Klasik Yöntem

// Singleton tasarım deseninin Java'da klasik uygulaması 
class Singleton {
 
    private static Singleton instance; 
  
    // Singleton nesnesi oluşturmak için getInstance () kullanımını zorlayan özel kurucu 
    private Singleton() {} 
  
    public static Singleton getInstance() { 
        if (instance == null) 
            instance = new Singleton(); 
        return instance; 
    } 
}

Bu yöntemde nesne ilk defa kullanılmak istendiği sırada yaratılmaktadır. Bu nesne her kullanılmak istendiğinde tekrar yatılmaması için “instance == null” koşulu kullanılmaktadır.

Fakat bu klasik yöntem thread safe bir yapıda değildir. Aynı anda iki thread iki farklı nesne (veya daha fazla thread daha fazla nesne) oluşturabilir. Bu yüzden klasik yönteme thread safe bir yapı kazandırmamız gerekmektedir.


Yöntem 2. Eşzamanlı getInstance()

// Singleton tasarım deseninin thread eşzamanlı java uygulaması
class Singleton { 

    private static Singleton instance; 
  
    private Singleton() {} 
  
    // Bunu aynı anda yalnızca tek bir thread yürütebilir 
    public static synchronized Singleton getInstance() { 
        if (instance == null) 
            instance = new Singleton(); 
        return instance; 
    } 
}

Burada synchronized kullanarak, bir seferde sadece bir iş parçacığının (thread) getInstance() işlevini yürütebilmesini sağlamış oluyoruz.

Bu yöntemin dezavantajı, nesneyi oluştururken her seferinde synchronized kullanmanın (kontrolünün) pahalı olması ve programın performansını düşürebilmesidir. Ancak, getInstance() uygulamasının performansı uygulama için kritik değilse, bu yöntem temiz ve basit bir çözüm sağlamaktadır.


Yöntem 3. İstekli Yükleme

// Singleton tasarım deseninin statik başlatıcı tabanlı java uygulaması
class Singleton { 

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

Burada ise nesne, sınıf belleğe yüklendiği anda oluşturulmaktadır. Bu yöntem yalnızca singleton sınıfına programın başlatılması sürecinde ihtiyaç duyuluyorsa kullanılmalıdır.


Yöntem 4. Çift Kontrol Kilitleme

Dikkat ettiğimizde, bir nesne oluşturulduktan sonra senkronizasyon artık yararlı olmaz çünkü artık instance null olmayacak ve herhangi bir işlem sırası tutarlı sonuçlar doğuracaktır.

Bu yüzden, instance null olduğunda, sadece bir kez getInstance() üzerindeki kilidi geçerli olur. Bu şekilde sadece ilk adımda senkronizasyon elde etmiş oluruz.

// Singleton tasarım deseninin çift kontrollü kilitleme tabanlı Java uygulaması
class Singleton { 

    private volatile static Singleton instance; 
  
    private Singleton() {} 
  
    public static Singleton getInstance() { 
        if (instance == null) { 
            // Thread safe
            synchronized (Singleton.class) { 
                // Birden fazla thread buraya ulaşabileceğinden tekrar kontrol
                if (instance == null) 
                    instance = new Singleton(); 
            }
        }
        return instance; 
    } 
}

Singleton instance başlatıldığında, birden çok iş parçacığının nesne değişkenini doğru bir şekilde sunmasını sağlayan tarafsızlığı tanımlamış olduk. Bu yöntem ile senkronize metodu her seferinde çağıran ek yükü büyük ölçüde azaltmış oluyoruz.

Referanslar

  1. https://en.wikipedia.org/wiki/Singleton_pattern
  2. https://www.geeksforgeeks.org/singleton-design-pattern/
  3. https://bidb.itu.edu.tr/eskiler/seyirdefteri/blog/2013/09/08/yegane-tasar%C4%B1m-kal%C4%B1b%C4%B1-(singleton-design-pattern)
  4. https://www.tutorialspoint.com/design_pattern/singleton_pattern.htm
  5. https://sourcemaking.com/design_patterns/singleton