|
"Singleton" Tasarım Deseninin(Pattern) C# ile Gerçekleştirilmesi |
|
Gönderiliyor lütfen bekleyin... |
|
|
Yazılım mühendisliğinin sanatsal yönü ağır olan
"design pattern" kavramını bir çoğumuz mutlaka duymuşuzdur, ama rutin
işlerimizden kendimizi boşa çıkarıp bir türlü inceleme fırsatı bulamamışızdır,
Bu ve bundan sonraki bir kaç makalelik dizide size kendi terminolojik
yapısı içinde deyimleşmiş olan "design pattern" yani "desen tasarımı"
kavramını açıklamaya çalışacağım. Elbette açıklamalarımı en çok bilinen
tasarım desenleri ile destekleyeceğim. Bu konudaki ilk makalede en basit ve en
popüler tasarım desenlerinden biri olan "Singleton" deseninden bahsedip
"pattern design" sanatına daha farklı bir bakış açısıyla yaklaşmanızı sağlamaya
çalışacağım. O halde işe basit tanımlarla başlayalım.
"Design Pattern" Nedir ?
Bildiğiniz üzere günümüzde yazılım mühendisliği alanında en fazla ses getiren
kurgu yazılımın gerçek dünya ile olan ilişkisinin sağlanabilmesidir. Bu ilişki
elbette nesne yönelimli programlama tekniği ile sağlanmaktadır. Nesne yönelimli
programlama tekniği bilgisayar uygulamalarını soyut bir olgudan çıkararak
insanların daha kolay algılayabileceği hale getirmiştir. Öyle görünüyorki,
makro düzeyde gerçek hayatı modelleme ile başlayan bu ilişki mikro düzeydede
büyük ses getirecektir. Nitekim son yıllarda geliştirilen yapay sinir ağları
ile makinelerin çalışma sistemlerinin gün geçtikçe insanların veya canlıların
çalışma şekline yaklaştığı görülmektedir. Artık bilgisayarlardan sadece verilen
komutları yerine getirmek değil, belirli olaylar ve durumlar karşısında bazı
hükümlere varabilmeleride istenmektedir. Burada vurgulamak istediğim nokta
şudur : bizler yazılım mühendisleri veya programcılar olarak gerçek hayatı ne
kadar iyi modelleyebiliyorsak o kadar başarılı sayılırız. Peki "desgin
pattern" konusu nerede devreye girmektedir? İşte benimde gelmek istediğim nokta
budur; "desgin patterns" bir modelin tasarımın ustaca tasarlanmasını sağlayacak
çeşitli desenlerin oluşturulmasını ve bu desenlerin ihtiyaç dahilinde herhangi
bir modelin inşaasında kullanılabilmesini sağlar. "Design pattern" kavramı bir
kurallar topluluğundan ziyade bir işi nasıl ve en güzel ne şekilde
yapabileceğimiz gösteren yöntemler topluluğudur. Öyleki iyi bir yazılım
modelleyicisiyseniz kendi tasarım desenlerinizi oluşturabilir ve bunları diğer
ustaların kullanımına sunabilirsiniz. Tasarım desenleri tecrübe ile oluşturulan
yapılardır. Bazıları olmazsa olmaz yapılar olmasına rağmen bazıları
tamamen yazılımın sanatsal yönünü göstermek için tasarlanmıştır . Örneğin
bu yazımın ana konusunu belirleyen "Singleton" tasarım deseni yıllardan beri
bir çok kişi tarafından kullanılmıştır. Sizde bu yazıda bu desenin amacını ve
nasıl uygulandığını öğrendiğinizde eminimki projelerinizde mutlaka
kullanacaksınız. Hemen şunuda belirteyimki bu tasarım deseni sizi uzaya
götürmeyecektir, bu yüzden beklentilerinizi biraz daha azaltmanızda fayda var.
O halde "design pattern" yada "tasarım deseni" ni şu şekilde tanımlayabiliriz :
Bir tasarım problemini en basit ve en efektif bir şekilde çözüme kavuşturacak
yöntemdir.
"Design Pattern" Kaynakları
"Design Pattern" konusunda yazılmış en güzel ve en popüler kaynaklardan
biri Erich Gamma, Richard Helm, Ralph Johnson ve John Vlissides
tarafından kaleme alınmış "Design Patterns: Elements of Reusable Object-Oriented
Software" kitabıdır. Bu kitapta en popüler tasarım desenleri
anlatılmış ve bu desenlerin çeşitli uygulamalarına yer verilmiştir. "Desgin
pattern" guru'ları olarak anılan bu 4 kişi "Gangs Of Four(GOF)" olarak ta
bilinmektedir. Zaten bahsi geçen kitapta anlatılan tasarım desenlerine de
genel olarak GoF tasarım desenleri denilmektedir. Bu yazı ile başlayan yazı
dizisinde GOF olarak anılan tasarım desenlerini sizlere aktarıp çeşitli
kullanım alanlarını açıklayacağım.
GOF tasarım desenleri genel olarak 3 ana grup altında incelenir. Bu gruplar ve
herbir gruptaki tasarım desenlerinin isimleri aşağıda verilmiştir.
1 - Creatinal Patterns Bu desenler bir yada daha fazla
nesnenin oluşturulması ve yönetilmesi ile ilgilidir. Örneğin bu yazıda
anlatacağım ve bir uygulamanın ömrü boyunca belirli bir nesneden sadece bir
adet bulunmasını garantileyen Singleton deseni bu gruba girmektedir. Bu
gruptaki diğer desenler ise
Abstract Factory
Builder
Factory Method
Prototype
olarak bilinmektedir. Bu desenlerin bir çoğunu ilerleyen yazılarımda ele
alacağım. Şimdilik sadece bir giriş yapıyoruz.
2 - Behavioral Patterns Bu gruptaki desenlerin
amacı belirli bir işi yerine getirmek için çeşitli sınıfların nasıl birlikte
davranabileceğinin belirlenmesidir. Bu gruptaki desenler ise aşağıdaki
gibidir.
Chain of responsibility
Command
Interpreter
Iterator
Mediator
Memento
Observer
State
Strategy
Template method
Visitor
3 - Structural Patterns Bu gruptaki desenler
ise çeşitli nesnelerin birbirleri ile olan ilişkileri temel alınarak
tasarlanmıştır. Bu gruptaki tasarım desenleri ise şunlardır:
Adapter
Bridge
Composite
Decorator
Façade
Flyweight
Proxy
Bu giriş bilgisinden sonra şimdi nesnelerin yaratılması ile ilgili grup olan
"Creatinal Patterns" grubunda bulunan "Singleton" desenini açıklamaya
başalayabiliriz.
Singleton Deseni
Singleton deseni bir programın yaşam süresince belirli bir nesneden sadece bir
örneğinin(instance) olmasını garantiler. Aynı zamanda bu
desen, yaratılan tek nesneye ilgili sınıfın dışından global düzeyde
mutlaka erişilmesini hedefler. Örneğin bir veritabanı uyglaması
geliştirdiğinizi düşünelim. Her programcı mutlaka belli bir anda sadece bir
bağlantı nesnesinin olmasını isteyecektir. Böylece her geretiğinde yeni bir
bağlantı nesnesi yaratmaktansa varolan bağlantı nesnesi kullanılarak sistem
kaynaklarının daha efektif bir şekilde harcanması sağlanır. Bu örnekleri dahada
artırmak mümkündür. Siz ne zaman belli bir anda ilgili sınıfın bir örneğine
ihtiyaç duyarsanız bu deseni kullanabilirsiniz.
Peki bu işlemi nasıl yapacağız.? Nasıl olacakta bir sınıftan sadece ve sadece
bir nesne yaratılması garanti altına alınacak? Aslında biraz düşünürseniz
cevabını hemen bulabilirsiniz! Çözüm gerçekten de basit : statik üye
elemanlarını kullanarak.
Singleton tasarım desenine geçmeden önce sınıflar ve nesneler ile ilgili temel
bilgilerimizi hatırlayalım. Hatırlayacağınız üzere bir sınıftan yeni bir nesne
oluşturmak için yapıcı metot(constructor) kullanılır. Yapıcı metotlar C#
dilinde new anahtar sözcüğü kullanılarak aşağıdaki gibi çağrılabilmektedir.
Sınıf nesne = new Sınıf();
Bu şekilde yeni bir nesne oluşturmak için new anahtar sözcüğünün temsil ettiği
yapıcı metoduna dışarıdan erişimin olması gerekir. Yani yapıcı metodun
public olarak bildirilmiş olması gerekir. Ancak "Singleton" desenine göre
belirli bir anda sadece bir nesne olabileceği için new anahtar sözcüğünün
ilgili sınıf için yasaklanması gerekir yani yapıcı metodun protected yada
private olarak bildirilmesi gerekir. Eğer bir metodun varsayılan yapıcı
metodu(default constructor- parametresiz yapıcı metot) public olarak
bildirilmemişse ilgili sınıf türünden herhangi bir nesnenin sınıfın dışında
tanımlanması mümkün değildir. Ancak bizim isteğimiz yalnızca bir nesnenin
yaratılması olduğuna göre ilgili sınıfın içinde bir yerde nesnenin
oluşturulması gerekir. Bunu elbette statik bir özellik(property) yada statik
bir metotla yapacağız. Bu statik metot sınıfın kendi içinde yaratılan nesneyi
geri dönüş değeri olarak bize gönderecektir. Peki bu nesne nerde ve ne zaman
yaratılacaktır? Bu nesne statik metodun yada özelliğin içinde yaratılıp
yine sınıfın private olan elemanına atanır. Tekil olarak yaratılan bu nesne her
istendiğinde eğer nesne zaten yaratılmışsa bu private olan elemanın referasına
geri dönmek yada nesneyi yaratıp bu private değişkene atamak gerekmektedir.
Sanırım bu deseni nasıl uygulayabileceğimizi kafanızda
biraz canlandırdınız. O halde daha fazla uzatmadan desenimizi uygulamaya
geçirelim.
Singleton Deseninin 1. versiyonu
public
class SingletonDeseni
{
private static
SingletonDeseni nesne =
new
SingletonDeseni();
private
SingletonDeseni()
{
}
public static
SingletonDeseni Nesne
{
get
{
return
nesne;
}
}
}
|
Yukarıdaki sınıf örneğinde SingletonDeseni sınıfı
belleğe yüklendiği anda statik olan SingletonDeseni nesnesi yaratılacaktır. Bu
nesne yaratılışının new anahtar sözcüğü ile yapıldığına dikkat edin. Eğer siz
Main() gibi bir metodun içinden bu nesneyi yaratmaya kalksaydınız derleme
aşamasında hata alırdınız. Çünkü public olan herhangi bir yapıcı metot
bulunmamaktadır. Ayrıca
Siz Main() gibi bir metodun içinden yaratılan bu nesneye
SingletonDeseni nesne = SingletonDeseni.Nesne;
şeklinde erişmeniz mümkündür. Böylece yukarıdaki deyimi her kullandığınızda
size geri dönen nesne, sınfıın belleğe ilk yüklendiğinde yaratılan nesne olduğu
garanti altına alınmış oldu. Dikkat etminiz gereken diğer bir nokta ise nesneyi
geri döndüren özelliğin yalnızca get bloğunun olmasıdır. Böylece bir kez
yaratılan nesne harici bir kaynak tarafından hiç bir şekilde
değiştirilemeyecektir.
Yukarıdaki SingletonDeseni sınıfını aşağıdaki gibi de yazmamız mümkündür.
Singleton Deseninin 2. versiyonu
public
class SingletonDeseni
{
private static
SingletonDeseni nesne =
new
Singleton();
private
SingletonDeseni()
{
}
public static
Singleton Nesne()
{
return
nesne;
}
}
|
Dikkat ederseniz iki sınıfın tek farkı oluşturulan
nesneye erişme biçimidir. İlk versiyonda nesneye özellik üzerinden erişilirken
ikinci versiyonda metot üzerinden erişilmektedir. Değişmeyen tek nokta
ise her iki erişim aracının da statik olmasıdır.
Yukarıdaki her iki versiyonda da biz yaratılan nesneyi
SingletonDeseni nesne = SingletonDeseni.Nesne;
yada
SingletonDeseni nesne = SingletonDeseni.Nesne();
şeklinde istediğimizde nesne zaten yaratılmış durumda olmaktadır. Oysa bu
sınıfı daha efektif bir hale getirerek yaratılacak nesnenin ancak biz onu
istediğimizde yaratılmasını sağlayabiliriz. Bu durumu uygulayan Singleton
deseninin 3 versiyonunu olarak aşağıda görebilirsiniz.
Singleton Deseninin 3. versiyonu
public
class SingletonDeseni
{
private static
SingletonDeseni nesne;
private
SingletonDeseni()
{
}
public static
Singleton Nesne()
{
if(nesne
== null)
nesne
= new SingletonDeseni();
return
nesne;
}
}
|
Gördüğünüz üzere nesne ilk olarak sınıf belleğe
yüklendiğinde değilde o nesneyi ilk defa kullanmak istediğimizde yaratılıyor.
İlgili nesneyi her istediğimizde yeni bir nesnenin yaratılmaması içinde
if(nesne == null)
şeklinde bir koşul altında nesnenin yaratıldığına dikkat edin.
Not : 3.versiyonda nesneyi yaratan bir metot olabileceği gibi 1.
versiyondaki gibi sadece get bloğu olan özellikte olabilir.
Herşeye rağmen yukarıdaki 3 versiyonda bazı durumlar için tek
bir nesnenin oluşmasını garanti etmemiş olabilirz. Eğer çok
kanallı(multi-thread) bir uygulama geliştiriyoırsanız farklı kanalların aynı
nesneyi tekrar yaratması olasıdır. Ancak eğer çok kanallı
çalışmıyorsanız(çoğunlukla tek thread ile çalışırız) yukarıdaki sade ama
öz olan 3 versiyondan birini kullanabilirsiniz. Ama eğer çok kanallı
programlama modeli söz konusu ise ne yazıkki farklı kanalların aynı nesneden
tekrar yaratmasını engelemek için ekstra kontroller yapmanız gerekmektedir. Ne
yazıkki diyorum çünkü bu yapacağımız kontrol performansı büyük ölçüde
düşürmektedir.
O halde çok kanallı uygulamalarda kullanabileceğimiz Singleton desenini
yazalım.
Singleton Deseninin 4. versiyonu
public
class SingletonDeseni
{
private static
SingletonDeseni nesne;
private static
Object kanalKontrol =
new Object;
private
SingletonDeseni()
{
}
public static
Singleton Nesne()
{
if(nesne
== null)
{
lock(kanalKontrol)
{
if(nesne
== null)
{
nesne
= new SingletonDeseni();
}
}
}
return
nesne;
}
}
|
Yukarıdaki desendeki püf nokta lock anahtar
sözcüğünün kullanımıdır.Eğer nesne ilk defa yaratılcaksa yani daha önceden
nesne null değere sahipse lock anahtar sözcüğü ile işaretlenen blok kitlenerek
başka kanalların bu bloğa erişmesi engellenir. Böylece kilitleme işlemi
bittiğinde nesne yaratılmış olacağı için, kilidin kalkmasını bekleyen diğer
kanal lock bloğuna girmiş olsa bile bu bloktaki ikinci if kontrolü nesnenin
yeniden oluşturulmasını engelleyecektir. Böylece çok kanallı uygulamalar içinde
tek bir nesnenin oluşmasını ve bu nesneye erişimi garanti altına alan Singleton
desenini tasarlamış olduk.
Son olarak lock anahtar sözcüğünü kullanmadan çok kanallı uygulamalar içinde
tek bir nesneyi garanti altına alacak deseni yazalım. Aşağıda Singleton desenin
5. versiyonu bulunmaktadır.
Singleton Deseninin 5. versiyonu
public
class SingletonDeseni
{
private
static SingletonDeseni nesne =
new
SingletonDeseni ();
private
static SingletonDeseni()
{
}
private
SingletonDeseni()
{
}
public static SingletonDeseni Nesne
{
get
{
return
nesne;
}
}
}
|
Bu versiyonun birinci versiyondan tek farkı yapıcı
metodunda statik olmasıdır. C# dilinde statik yapıcı metotlar bir uygulama
domeninde ancak ve ancak bir nesne yaratıldığında yada statik bir üye eleman
referans edildiğinde bir defaya mahsus olmak üzere çalıştırılır. Yani
yukarıdaki versiyonda farklı kanalların(thread) birden fazla SingletonDeseni
nesnesi yaratması imkansızdır. Çünkü static üye elemanlar ancak ve ancak bir
defa çalıştırılır.
Son versyion basit ve kullanışlı görünmesine rağmen kullanımının bazı
sakıncaları vardır. Örneğin Nesne Özelliği dışında herhangi bir statik üye
elemanınız var ise ve ilk olarak bu statik üye elemanını kullanıyorsanız siz
istemedğiniz halde SingletonDeseni nesnesi yaratılacaktır. Zira yukarıda da
dediğimz gibi bir statik yapıcı metot herhangi bir statik üye elemanı
kullanıldığı anda çalıştırılır. Diğer bir sakıncalı durumda birbirini çağıran
statik yapıcı metotların çağrılması sırasında çelişkilerin oluşabileceğidir.
Örneğin her static yapıcı metot ancak ve ancak bir defa çalıştırılır
dedik. Eğer çalıştırılan bir static metot diğer bir statik metodu çağırıyor ve
bu statik metotta ilkini çağırıyorsa bir çelişki olacaktır.
Kısacası eğer kodunuzun çelişki yaratmayacağından eminseniz 5. deseni
kullanmanız doğru olacaktır. Eğer çok kanallı uygulama geliştiriyorsanız 4.
versiyonu, çok kanallı uygulama geliştirmiyorsanızda 3. versiyonu kullanmanız
tavsiye edilmektedir.
Singleton deseni konulu makalenin sonuna gelmiş bulunmaktayız. Eğer ileride bir
gün yukarıdaki desenlerin birini kullanma ihtiyacı hissederseniz hangi deseni
ne amaçla kullandığınızı bizimle paylaşırsanız seviniriz.
Bir diğer "Creational Patterns" deseni olan "Abstract Factory" desenini
anlatacağım yazıda görüşmek üzere.
Makale:
"Singleton" Tasarım Deseninin(Pattern) C# ile Gerçekleştirilmesi C#, Visual C# ve .NET Sefer Algan
|
|
|
-
-
Eklenen Son 10
-
Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
|
|