Sansür, bir toplumun kendine olan güvensizliğini yansıtır ve otoriter rejimlerin belirgin bir özelliğidir.

--Potter Stewart

14.11.2008

En Basit Tasarım Örüntüsü Singleton (mu?)

Singleton örüntüsü bir sınıfın sadece tek bir nesnesi olması gerektiği durumlarda kullanılır ve sınıfın ihtiyaç duyulduğu zaman yaratıldığı en bilindik kullanım şekli şu şekildedir:

public class DateUtils {


private static DateUtils instance = null;


private DateUtils() {}


public static DateUtils getInstance() {


if(instance == null)


instance = new DateUtils();


return instance;


}

...

}


Böyle bir kullanım çoklu işletim dizilerinde (multithreads) sorunlara neden olabilmektedir. Aynı anda iki farklı işletim dizisinin instance niteliğini kontrol etmesi ve null görmesi sonucu iki farklı olgunun yaratılma olasılığı vardır. Bunun önüne iki şekilde geçilebilir. İlki sınıfın static niteliğinin uygulama ayağa kalkarken yaratılması:


public class DateUtils {


private static DateUtils instance = new DateUtils();


private DateUtils() {}


public static DateUtils getInstance() {

return instance;

}

...

}

İkincisi ise getInstance() yönteminin synchronize hale getirilmesi. Tüm yöntemin senkron hale getirilmesi, sadece nesnenin null durumunda kontrol edilmesi gereken, nesne yaratıldıktan sonra da performansa olumsuz etki yapan bir durum olduğu için kullanımından kaçınılmaktadır. Bunun yerine instance niteliği null ise senkronu başlatan bir yöntem tercih edilmiştir:


public class DateUtils {


private static DateUtils instance;


private
DateUtils() {}

public static DateUtils getInstance () {


if(instance == null) {


synchronized(DateUtils.class)
{


if(instance == null)


instance = new DateUtils();


}


}


return instance;


}

}

Ne var ki “Double-Checked Locking” olarak bilinen bu yöntem JDK 5’ten önce çalışmıyor. Ayrıntılı bilgiye “The Double-Checked Locking is Broken Declaration” bağlantısından ulaşabilirsiniz. JDK 5 ile gelen volatile bu
sıkıntıya derman oluyor:


public class DateUtils {


private volatile static DateUtils instance;


private DateUtils() {}


public static DateUtils getInstance () {


if (instance == null) {


synchronized(DateUtils.class)
{


if (instance == null)


instance = new DateUtils();


}


}


return instance;


}

}

Singleton örüntüsünde dikkat edilmesi gereken bir başka husus ise sınıf Clonable arayüzünü gerçekleştiren bir başka sınıftan türetilmişse ortaya çıkıyor. Singleton sınıfımızın clone() yöntemi ile çoğaltılmasının önüne geçmek istiyorsak bu metodun üstüne yazmamız gerekiyor:

public Object clone() throws CloneNotSupportedException {


throw new CloneNotSupportedException();

}

Hiç yorum yok:

Yorum Gönder