Singleton (Tek Nesne) Design Pattern
02-07-2016 Okuma Modu
Uygulama geliştirirken en popüler tasarım desenlerinden biri singleton yani tek nesne tasarım desenidir.
İsminden de anlaşılacağı üzere singleton tasarım deseni, hazırlayacağımız sınıftan sadece bir örneğinin oluşturulmasını sağlar. Bu sayede nesnenin kopyalanmasını yada yeni bir tane oluşturmasını engeller ve nesneye ihtiyaç duyulduğunda o nesnenin daha önceden oluşturulan örneği çağırır.
Ne zaman kullanırız?
Veritabanı bağlantılarında, port bağlantılarında, yada dosya işlemleri gibi tek bir nesneye ihtiyaç duyduğumuz zamanlarda kullanırız.
Nasıl Yaparız?
Daha önceki yazılarımı okuduysanız dışarıdan nesne oluşturduğumuzda ilk başta construct
yani kurucu metotun çalıştığını bilmeniz gerekir. Construct sihirli metotunu private
yada protected
yaparsak nesne oluşturmasını yalnızca sınıfın içinde veya miras alan sınıf içinde tanımlayabiliriz.
public class SingletonObject
{
// Nesnemizin daha önceden oluşturulmadığını anlayabilmemiz için statik instance özelliği tanımlıyoruz.
private static SingletonObject instance = null;
//Sınıfımızın construct (kurucu) metodunu private yada protected tanımlıyoruz.
private SingletonObject()
{
// oluşturulma sırasında kullanacağımız kodlar
}
// Dışarıdan sınıfımızı çağıracağımız metodumuz.
public static SingletonObject getInstance()
{
// eğer daha önce örnek oluşturulmamış ise sınıfın tek örneğini oluştur
if(instance == null)
{
instance = new SingletonObject();
}
return instance;
}
}
Yukarıdaki gibi bir sınıf oluşturduğumuzda dışarıdan new SingletonObject()
dediğimizde hata verdiğini göreceksiniz. Bir önceki yazımda tasarım desenlerinin programlama dili gözetmeksizin bir standardı olduğunu söylemiştim, bunu pekiştirmek adına bir de PHP de nasıl olacağını görelim.
<?php
class SingletonObject
{
// Nesnemizin daha önceden oluşturulmadığını anlayabilmemiz için statik instance özelliği tanımlıyoruz.
private static $instance = null;
//Sınıfımızın construct (kurucu) metotu private yada protected tanımlıyoruz.
private function __construct()
{
// oluşturulma sırasında kullanacağımız kodlar
}
// Dışarıdan sınıfımızı çağıracağımız metodumuz.
public static function getInstance()
{
// eğer daha önce örnek oluşturulmamış ise sınıfın tek örneğini oluştur
if (static::$instance == null) {
static::$instance = new static();
}
return static::$instance;
}
}
Gördüğünüz gibi mantık aynı, peki bu işlemler yeterli mi, başka türlü nesne oluşturabilir mi? Tabi ki evet, sınıftan yeni bir örnek oluşturamasak da var olan örneği kopyalayabiliriz, bu yüzden bunuda engellemek için clone
sihirli metoduna düzenleme yapmalıyız.
Son olarak JAVA'ya özgü thead (kanal) yapısı sayesinde birden fazla kanaldan aynı anda getInstance
metoduna istek yaparsak ve daha önce oluşturmadıysak birden fazla örnek oluşturmuş oluruz, bunu engellemek içinde metodumuzun başına synchronized anahtar kelimesini ekleyerek bu işlemleri sıraya koyar ve birden fazla oluşmasını engelleriz.
Lafı fazla uzatmadan son haline bakalım
public class SingletonObject
{
// Nesnemizin daha önceden oluşturulmadığını anlayabilmemiz için statik instance özelliği tanımlıyoruz.
private static SingletonObject instance = null;
//Sınıfımızın construct (kurucu) metodunu private yada protected tanımlıyoruz.
private SingletonObject()
{
// oluşturulma sırasında kullanacağımız kodlar
}
// Dışarıdan sınıfımızı çağıracağımız metodumuz.
// synchronized anahtar kelimemiz ile metodun aynı anda çalışmasını engelledik.
public synchronized static SingletonObject getInstance()
{
// eğer daha önce örnek oluşturulmamış ise sınıfın tek örneğini oluştur
if(instance == null)
{
instance = new SingletonObject();
}
return instance;
}
//Sınıfı clone sihirli metoduyla kopyalamaya çalıştığımızda CloneNotSupportedException ile kopyalanmasını engelliyoruz.
@Override
public Object clone() throws CloneNotSupportedException
{
throw new CloneNotSupportedException("Ben eşsiz bir parçayım");
}
}
Yukarıda PHP'den de bahsettik o zaman onunda son haline bakalım
<?php
class SingletonObject
{
// Nesnemizin daha önceden oluşturulmadığını anlayabilmemiz için statik instance özelliği tanımlıyoruz.
private static $instance = null;
//Sınıfımızın construct (kurucu) metotu private yada protected tanımlıyoruz.
private function __construct()
{
// oluşturulma sırasında kullanacağımız kodlar
}
// Dışarıdan sınıfımızı çağıracağımız metodumuz.
public static function getInstance()
{
// eğer daha önce örnek oluşturulmamış ise sınıfın tek örneğini oluştur
if (static::$instance === null) {
static::$instance = new static();
}
return static::$instance;
}
// dışarıdan kopyalanmasını engelledik
private function __clone()
{
}
// unserialize() metodu ile tekrardan oluşturulmasını engelledik
private function __wakeup()
{
}
}
Bu yazıma özel hem JAVA hem de eski dost PHP'de singleton tasarım deseni nasıl uygulanır ona değindim. Bundan sonraki yazılarımda yüksek ihtimal yalnızca JAVA ile ilerleyeceğim ama yukarıdaki örnekten de anlaşılacağı üzere mantıkları birebir aynıdır. Yani bu tasarım desenlerinin dili yok.
Kendinize iyi bakın :)