Design Patterns
Tasarim
Desenleri Nedir?
Nesne
yönelimli programlamada, sinif ve nesneler arasindaki iliskinin
en iyi nasil olmasi gerektigini açiklayan yönteme tasarim
desenleri denir. Algoritmalar programin matematiksel olarak nasil
çalismasi gerektigine karar verdigimiz yerken, tasarim
desenleri yazilim tasarimi sorunlariyla ilgilenir. Tasarim
desenleri, yazilim tasariminda karsimiza çikan sorunlari
esnek, yeniden kullanilabilir, basarili çözümler getiren bir
takim hazir kaliplardir.
1994
yilinda ise, Gang of Four (dörtlü çete) olarak bilinen "Erich
Gamma", "Richard Helm", "Ralph Johnson" ve
"John Vlissides" isimli yazarlar "Design Patterns:
Elements of Reusable Object-Oriented Software" adli kitabi
yazdilar ve bu en yaygin olarak kullanilan 23 deseni en çok
kullanilan isimleriyle bu kitapta topladilar.
En Yaygin 23 Tasarim Deseni
Creator Design Patterns (Kurucu Tasarim Desenleri)
Abstract
Factory (Soyut Fabrika)
Builder
(Kurulum Nesnesi)
Factory
Method (Fabrika Yordami)
Prototype
(Kopya Nesne)
Singleton
(Tek Nesne)
Structural Design Patterns (Yapisal Tasarim Desenler)
Adapter
(Adaptör)
Bridge
(Köprü)
Composite (Agaç Yapisi)
Decorator (Dekorasyon)
Facade (Ön Yüz)
Flyweight (Hafif Agirlik)
Proxy (Özdes Nesne)
Behavioral Design Patterns (Davranissal Tasarim Desenler)
Chain of Responsibility
(Sorumluluk Zinciri)
Command (Komut)
Interpreter (Yorumlayici)
Iterator (Tekrarlayici)
Mediator (Arabulucu)
Memento (Hatirlayici)
Observer (Gözlemci)
State (Durum)
Strategy (Strateji)
Template Method (Kalip
Yordam)
Visitor (Ziyaretçi)
Creational Pattens (Kurucu Tasarim Deseni):
Abstract Factory (Soyut Fabrika):
Bazi
durumlarda birbiriyle iliskili biden fazla nesne yaratmak gerekir.
Örnegin
yandaki sekilde ProductA1
sinifi nesnesi ile ProductB1 sinifi
nesnesi bilikte kullanilacaktir. Benze sekilde ProductB2
ve ProductA2
nesneside birlikte
kullanilacaktir bu durumda birbirleriyle iliskili nesneleri
yaratan(Nesne Ailesi) farkli fabrika siniflari olusturulur.
Bu fabrika siniflari ortak bir soyut fabricadan üretilir.
Builder (Kurulum Nesnesi):
Kurulumu
saglayan bir çok kurucu nesne olabilir. Tek bir genel kurucu üst
sinif altinda toplanirlar.
Kurucu
nesnelerden birini alip kurulumu yöneten bir tane yönetici sinif
olur. Client belli bir parametreye göre kurucu nesneyi seçer ve
bunu yönetici sinifa geçirir. Ardindan yönetici sinif
ihtiyaci olan nesneyi alir.
Bu
desen kurucu bir desen oldugu için nesne olusturma ve yaratma
sorumlulugunu ilgili desene verir. Ayrica varsayilan degerler
kullanildigi için nesnenin yaratilmasi basitlesir ve bir
düzen içinde gerçeklesir.
Ayrica
üst sinifin kurulum nesnesinin altina baska kurulum nesneleride
gelebilir, sistemin genislemesinide bu sekilde kolaylastirmis
oluruz.
Bu
deseni yaratilacak nesne karmasik, anlasilmasi zor oldugunda
ve bir düzen içinde olmasi gerektigi durumlarda kullanabiliriz.
Factory (Fabrika Methodu) :
Bu desende yaratma isi ayri fabrika siniflari yerine methodlara atanir. Yaratici(fabrika) metotlar, yaratilan nesneleri kullanacak olan siniflarin üyeleri olabilirler; yani farkli neneler içinden içinden kendilerine uygun olanlari yaratip kullanabilirler.
Örnek
olarak; grafik ve metin dosyalarinin oldugu farkli tipteki
dosyalari kullanan farkli dokümanlar olsun. Grafik dosyasi
grafik, metin dosyasi da metin dosyalari otusturup kullansin.
Ileride sisteme yeni dosya tipleri ve ve yeni dokümanlarin
gelebilecegini düsünelim.
Çözüm
:
-
Tüm dosyalari Abstract bir taban siniftan üretmeliyiz.
-
Bu durumda hangi dokümanin olusturulacagina taban siniftan
üretilen nesne karar verir.
-
Yeni bir dosya olusturmak için alt sinif olusturuldugunda hangi
dokümanin olusacagina alt siniftaki fabrika metodunda karar
verilir .
Not: Fabrika metodunda yaratilan nesneleri yok etmek içinde “Dispose Method” kullanilabilir.
Not: Fabrika metodunda yaratilan nesneleri yok etmek içinde “Dispose Method” kullanilabilir.
Dispose
Method:
Desende
yönetilmeyen nesneler için Dispose methodunu kullanarak onlari
bellekten atabiliriz.
Bu
nesneleri using ifadeiyle ya da try-catch-finally blogunun
uygulandigi desenler yardimiyla bellekten atabilmek için,
nesnenin sart kostugu method “IDisposable” arayüzünün
yazilmasi gerekmektedir.
Prototype
(Kopya Nesne):
Spesifik
projelerde kullanilan ve oldukça faydali olan bir kaliptir. Data
sonradan olusturulacak nesneler için bir prototype görevi üstlenen
bir yapiyi olusturmak için kullanilir. Projenin bir çok
noktasinda kullanilan nesnelerin bir kopyasini alip islemlere
kopya nesneyle devam edilmek istendiginde bu method kullanilabilir.
Nesnelerin
kopyalanmsi islemi 2 sekilde yapilabilir;
-Shallow
Copy: Nesnelerin sadece referanslarinin kopyalandigi, klasik
atama islemlerinde meydana gelen kopyalama biçimidir. Nesnenin
sadece adresini kopyaladigi için bu yöntem prototype metoduna
uygun degildir.
-Deep
Copy bu yöntemde nesneler birebilir kopyalanirken yeni bir referans
degiskenine atanir. C#da deger türlerinin birbirine atanmasi bu
duruma bir örnek olabilir."Prototype"
deseninde söz konusu olan referans türden nesnelerin "deep
copy" yöntemi ile kopyalanmasidir.
Prototype Deseninde üç temel yapi bulunur.
Soyut Prototip: Kopyalanarak yeni nesnelerin olusturulacagi siniflar için temel teskil eden ve çogunlukla içinde kopyalama islemini görecek özet bir metodun bulundugu abstract siniftir yada içinde sadece bildirimlerin yer aldigi bir arayüzdür. Ihtiyaca göre bu yapi özet(abstract) bir sinif olabilecegi gibi bir arayüzde olabilir.
Somut
Prototip Nesneleri: Soyut
nesneleri uygulayan ve projelerde kullanilan gerçek nesneleri
temsil ederler. Kopyalama islemi soyut siniftan kalitilan bir
metot ile yapilir.
Istemci(Client)
Uygulama: Somut
prototip nesnelerinden birer kopyasini elde edecek metot, sinif
yada baska bir üye elemandir.
Not
: Görüldügü üzere, "Prototype" deseni daha önce
anlatmis oldugum desenlere nazaran çok kolay ve anlasilirdir.
Bu kolayligin en büyük nedenlerinden biriside nesnelerin
kopyalanmasi için .NET Framework’un saglamis oldugu
imkanlardir.
Bütün
bu bilgiler isiginda “Prototype” sinifinin UML diagrami
yandaki gibidir.
Singleton (Tek Nesne):
Örnek
olarak; okul sinifindan sadece tek bir nesne olusturulacak ve bu
okul nesnesine projenin gerekli yerlerinden erisilecek dersek bunu
nasil gerçeklestirebiliriz?
Okul
nesnesnesini kim yaratacak ve bu nesneye nasil erisilecek?
Problemimiz:
Bir siniftan sadece bir nesne yaratilmali, bu nesne diger
nesnelere global erisim hakkina sahip olmali.
Çözüm:
Sinifin içinde tekil nesne yaratip ,adresi döndüren statik bir
method yazalim. Çünkü static methoslar sinifa ait henüz bir
nesne olusturulmamis olsada çagirilabilirler. Bu static Method
çagrildiginda henüz bir nesne olusturulmamissa olusturup
adresi döndürür.
Structural
Design Patterns
(Yapisal Tasarim Desenler)
Adapter
(Adaptör):
Bu
kalip istenen isi yapan hazir siniflara sahip oldugunda ancak
bu hazir sinifin arayüzünün bizim bekledigimizden farkli
oldugu durumlarda kullanilir. Temel islevi bir sinifin
arayüzünü baska bir sekle döüstürmektir.
Adabtör
kalibi karmasik problemlerin çözümlerinde de kullanilabilir.
Tasarlanan sistemin ayni isi birden fazla farkli sinifla ya da
sistemle iletisime geçerek yaptigi durumlarda istenilen isi
yapan hazir siniflarin arayüzleri bekledigimiz gibi
olmayabilir.
Örnek
olarak ;
Problemimiz:
Istenilen isi yapan fakat farkli arayüzleri olan benzer birimler
için kararli tek bir arayüz nasil yaratilir?
Çözüm:
Birimin arayüz nesnesini adaptör nesnesi kullanarak baska bir
arayüze dönüstürelim.
Bridge
(Köprü):
Köprüleme
metodunda abstraction ve imlamentation'i ayri tutarark ikisinide
bagimsiz olarak degistirebiliriz. Burada kastedilen bir sinifin
islevlerini yerine getirebilmesi için kullanilan diger siniflarin
delegation'idir.
Örnek olarak : 2 farkli
program yardimiyla 2 farkli sekil çizmemiz gerekiyor.
Problem: Sekillere
nereden karar vericez ve hangi programla çilmeleri gerektigini
nasil belirleyecegiz?
Çözüm: Birden fazla
türde sekil ve birden fazla bu sekilleri çizebilecegimiz program
var. Ortak kavramlarimizi belirledik. Sekil sinifi degisik
sekillerin ortak özelliklerini barindiracak. Programlarin
bulundugu nesne zaten nasil çizilecegini bilmektedir.
Iki grup arasinda
iliski kurarken 2 olasiligimiz var ya sekiller çizim
programlarini kullanacak ya da çizim programlari sekilleri
kullanacak. Ilk olasilik nesne yönelimli programlamaya daha
uygun oldugu için ilk seçenegimizden yola çikarak diyebiliriz
ki sekiller bu durumda kullanilacak olan implementation için bir
isaretçi içerir bu da aradaki köprüdür.
Composite
(Agaç Yapisi):
Bazi
durumlarda bir nesne belli bir is için bir nesne ile
iliskilendirildigi gibi ayni is için bir nesne listesiylede
iliskilendirilebilir. Esnekligi saglamak istedigimiz durumlarda
nesneyle mi nesne grubuyla mi iliskili oldugumuzdan habersiz
olmamiz gerekir.
Problem: Nesne gruplari
veya birlesik nesneler tek bir nesne gibi çok sekilli olarak nasil
tanimlamlanir?
Çözüm: Birlesik ve
atomik nesneleri ayni soyut siniftan(ara yüzden) türetin,
birlesik nesneler için atomik nesneleri içeren bir liste
yerlestirin.
Decorator
(Dekorasyon):
Kalibin temel islevi
bir nesneye dinamik olarak yeni davranislar eklenmesini ve
çikarilmasini saglar.
Örnegin D nesnesi
d1,d2,d3 islemlerini yapiyor ancak bazen bu durum d4,d5,d1
sirasiyla da gerçeklesebiliyorsa bu durumda decorator kalibi
kullanabiliriz. Decorator kaliba göre bütün islemler ayri bir
decorator sinif gibi tasarlanir. Programin çalismasi
sirasinda decoratör siniflardan yaratilan nesneler duruma göre
siralanabilir.
Ayni arayüze sahip
olmalari için ortak bir listede yer alabilmeleri için bir soyut
decoratör sinifindan türetilebilir.(concrete component)
Facade
(Ön Yüz):
Diyelimki eski bir proje
var alinizde yakinda yerini yeni bir proje alacak böyle durumlarda
eski proje için bir ön yüz(cephe) olusturulur böylece eski
sistemle tek bir nesne üzerinden erisilir. Karmasik eski sistemin
bütün hizmetleri kullanilmayacaksa sadece gerekli olanlar
gösterilebilir. Ayrica cephe ardindaki degisiklikler asil
sistemi etkilemez.
Problem : degisik ara
yüzlerin kullanildigi karmasik bir altsistemimiz var. Ilerde
degisebilir ve alt sistemnin bazi özellikleri hala kullanilmak
durumunda kalinabilir. Alt sistemle baglanti nasil saglanir?
Çözüm:alt sisteme bir
önyüz nesnesi tanimlanir.(facade) Böylece önyüz nesnesi alt
sistemin bütün hizmetleri için araci olacaktir.
Flyweight
(Hafif Agirlik):
Çok
fazla nesnenin sistemde oldugu durumlarda, nesne sayisinin
sistemde problemlere neden olmamasi için kullanilan tasarim
desenidir. Hafif agirlik nesnelerini bir koleksiyonda tutmak
gerekir.tutulan nesnelerin durumlari az ise ortak nesnelerin sayisi
azalir ve bu koleksiyonun büyüklügünü de azaltmis oluruz.
Problem:Bir
islemci sinifi düsünelim ve birde islem sinifi düsünelin
islem sinifindaki her bir üye için farkli bir islem
gerçeklesiyor ise islemcide bu islem yükünü hafifletmek için
ne yapabiliriz?
Çözüm:her
bir islem için islemci sinifi olusturmak yerine bir havuz
olustugunda havuza kaydedilir ve her gelen islemde havuza bakar
varsa havuzdan kullanir yoksa olusturur böylece fazladan islem
olusturmamis oluruz.
Proxy
(Özdes Nesne):
Client
ve operasyonu gerçeklestiren methotlar arasinda bulunan bir yapi
görevi görür.
Uml
diyagramindaki Subject yapisi interface veya abstract sinif
olarak tasarlanir ve gerçeklestirilecek operasyonlarin tanimini
belirtir. RealSubject ve Proxy ise gerçek siniflardir.
RealSubject sinifi operasyonu gerçeklestirecek gerçek kodlari
barindirir. Proxy sinifi ise RealSubject sinifindaki
operasyonlari çalistirir. Yani burada proxy nesnesi client ve
operasyonu gerçeklestirecek metotlarin arasinda bulunan bir yapi
görevi görür.
Behavioral
Design Patterns
(Davranissal Tasarim Desenler)
Chain
of Responsibility (Sorumluluk Zinciri)
Bu
tasarim deseni, egerki bir dizi islem islem siniflarinda
tutuluyorsa ve bu islemlerin baslangiç islemleride varsa ki
islem sirasi olmali ki bu islem sirasini olusturmamizi
saglayan desendir.
Command
(Komut)
Kullanicinin istedigi
komut blogunu sarmalayarak bir nesne seklinde saklanmasini
saglar.
Sarmal kod halinde
saklanan bu kod blogu alici nesne için bir çözüm
olusturabilir. Çöüzmlerin nesneler halinde saklanmasinin da
getirisi olarak komut tasari kalibi ayni kod yapisinin tekrar
tekrar kullanilabilmesine olanak saglar.
Komut
tasarim kalibinin kullanildigi tüm durumlarda geçerli olan
bazi ortak terimler mevcuttur. Açiklamalari ile beraber bunlar;
-Komut
(Command) :Gerçeklestirilecek
islem için bir ara yüz tanimlar.
-Somut
Komut (Concrete Command):Alici
ve gerçeklestirilecek islemler arasinda bir bag kurar, alicida
karsilik düsen islemleri çagirarak çalistirma eylemini
gerçeklestirir.
-Istemci
(Client):Komut
nesnesini olusturur ve metodun sonraki zamanlarda çagrilabilmesi
için gerekli bilgiyi saglar.
-Çagirici
(Invoker):Metodun
ne zaman çagrilacagini belirtir.
-Alici
(Receiver):Kullanici
isteklerini gerçeklestirecek asil metod kodlarini içerir.
Interpreter
(Yorumlayici)
Interpreter
tasarim deseni, düzgün gramer ifadesindeki metinlerin sayisal
veya mantiksal olarak islenmesi gereken durumlarda kullanilir.
Düzgün gramer ifadesi olarak, metinde ki karakterlerin özel
karsiliklari oldugu metinler olarak düsünebiliriz.
Interpreter tasarim deseninde; bu özel ifadelerin islenmesi için
hepsi ayni ara yüz veya abstract sinifi uygulayan siniflar
tasarlanir. Interpreter tasarim deseni için Uml diyagrami
asagidadir.
Interpreter
tasarim deseninde 5 temel yapi bulunmaktadir.
-Context:
Islenilecek metin
-AbstractExpression:
Context de ki anlam teskil eden ifadeleri isleyecek siniflarin
uygulamasi gereken arayüz veya abstract sinif.
-TerminalExpression:
Eger özel anlam ifade eden karakter tek basina bir anlam ifade
ediyor ise yani kendinden önce veya sonra gelen karakterler ile bir
baglantisi olmadan yorumlaniyor ise bu siniflar
TerminalExression olarak ifade edilir. AbstractExpression nesnesini
uygularlar.
-NonterminalExpression:
TerminalExpression lar arasinda “ve” “esittir” gibi
birbirlerine bagli olmalari veya aralarinda isleme sokulmasi
gibi durumlarda NonerminalExpression tipindeki siniflar kullanilir.
TerminalExpression - NonterminalExpression tipleri arasinda da
iliski olabilir. NonterminalExpression siniflari içerisinde
AbstractExpression tipinde referans veya referanslar olmalidir.
-Client:
Context, TerminalExpression ve Nonterminal expression yapi
agaçlarini olusturur ve çözümleme metodunu çalistirir.
Iterator
(Tekrarlayici)
Nesne
tabanli dillerde uygulama gelistirilirken en sik kullanilan
yapilardan biri de koleksiyonlardir. Iterator tasarim deseni
ile koleksiyon yapisi bilinmesine ihtiyaç olmadan koleksiyon
elemanlari üzerinde islem yapilabilmesini saglar. Yani iterator
tasarim deseni kullanilarak koleksiyonun array, queue, list olmasi
önemli olmadan, ayni sekilde elemanlarinin elde edilmesi
saglanir. Koleksiyon içindeki nesnelerin nasil elde edilecegi
tercihe göre belirlenebilir. Yani sonraki, ilk, son, 3. Eleman gibi
istenilen sekilde elemanlara ulasilabilir. Iterator tasarim
deseninde 5 temel yapi bulunur.
-Iterator:
Koleksiyon elemanlari elde edilebilmesi için gerekli islemleri
tanimlar.
-Aggregate:
Koleksiyon barindiran nesnelerin Iterator tipinden nesne
olusturacagini belirten arayüzdür.
-Concrete
Aggregate: Koleksiyon barindiran nesnedir. Aggregate arayüzünü
uygular ve ilgili ConcreteIterator nesnesini olusturur.
-ConcreteIterator:
Aggregate yapisinda ki koleksiyon elemanlarinin elde edilmesini
saglayan metotlari barindiran yani Iterator arayüzünü
uygulayan gerçek iterator nesnesidir.
-Client:
Bu yapiyi kullanarak koleksiyon içindeki elemanlara erisen
yapidir.
-Iterator
tasarim deseni için uml diyagrami asagidadir.
Mediator
(Arabulucu)
Proje
büyüdükçe bir çok sinif ve hirerarsi içerir. Mediator bu
durumda yardimiza yetisiyor objelerin birbirlerini bilmelerine
gerek kalmadan islerini yapabilmelerini saglar.
Memento
(Hatirlayici)
Memento
tasarim deseni nesnenin bir halinin kopyasini alip sonra bu
kopyanin tekrar elde edilmesini saglar. Genelde geri al islemi
için kullanilir. Memento tasarim deseni 3 yapidan olusur.
-Originator:
Tamaminin veya bazi özelliklerinin kopyasinin tutulacagi
nesnedir. Memento nesnesini olusturan ve geri yüklenmesinden
sorumludur.
-Memento:
Originator nesnesinin saklanacak özelliklerinin tanimli oldugu
nesne.
-Caretaker:
Saklanacak olan memento nesnesinin referansini içinde barindiran
nesnedir.
Observer
(Gözlemci)
Bir
tasarim nesnesinde degisiklik oldugu durumlardan haberdan olmamiz
gerektiginde bu tasarim deseni kullanilir. Kisaca bir network
hattinda dinleyici olan bir çok nesne bir nesnenin durumunu sürekli
gözlemler. Degisiklik oldugunda gözlemcilere haber verilir.
State
(Durum)
Nesnenin
durumu degistiginde, davranisida degisiyorsa kisaca nesneler
farkli durumlarda farkli davranislar sergiliyorlarsa durum
tasarim deseni kullanilabilir. Durum tasarim deseninin özelligi
if/else, veya swich ifadeleriyle kontrol edilebilmesini saglar.
Strategy
(Strateji)
Uml
semasindan da anlasilacagi üzere Context nesnesi içinde
Strategy referansi barindirir yani Strategy arayüzünden türeyen
nesneleri barindirir. Strategy arayüzünde ise farkli sekillerde
gerçeklestirilecek islemler tanimlanir. Sifrele – SifreCoz,
Encrypte – Decrypte, LogYaz gibi. Bu islemler gerçeklestirilirken
direkt ConcreteStrategyA, ConcreteStrategyB nesneleri ile degil
Context nesnesi kullanilir. Context nesnesine hangi
ConcreteStrategy nesnesine göre çalisacagi verilir ve
kullanilacak islemler Context üzerinden çalistirilarak
verdigimiz ConcreteStrategy nesnesine göre islemi gerçeklestirmis
oluruz.
Template
Method (Kalip Yordam)
Üst
siniflarda yer alan kalip yordam, tüm alt siniflarin ihtiyaç
duydugu adimlari barindirir, her yerden ulasilabildigi gibi,
kaliplar olusturulurken detaylar alt siniflara birakilir.
Örnek
olarak
veri tabani kayit eklemek ve bir kaydin var olup olmadigini
veren islemleri ele alalim. Normalde connection bir kez açilir
fakat biz her islemde connecitonu açip islem bitince de
kapatacagimizi düsünelim.
Bu
senaryoya template tasarim deseni ile söyle bir çözüm
getirebiliriz. Islemlerin tanimli olacagi bir abstract sinif
tanimlariz. Bu sinifta connection açan OpenCon ve connectionu
kapatan CloseCon metotlarini tanimlayalim. Her tablo için kayit
ekleme ve kontrol etme islemleri farkli olacagindan Insert ve
CheckData metotlarini abstract olarak tanimlayalim ki Concrete
siniflarda bu metotlari overwrite edebilelim. Son olarak da Insert
ve CheckData islemlerini her gerçeklestirirken her seferinde
connectionu açma ve kapama islemlerini tekrar yazmamak için
TemplateInsert ve TemplateCheckData isimli iki metot daha ekleyip
içlerinde gerekli olan islemleri çalistiralim.
Visitor
(Ziyaretçi)
Çok
sayida farkli tipte nesneyle islem yapilmasi gerektigi
durumlarda kullanilir.
Islem
yapilacak nesnelerde her hangi bir degisiklik yapilmaz ziyaretçi
nesneler olusturulur. Eger sisteme yeni nesneler eklenmiyor ama
yeni islemler ekleniyorsa bu yöntem kullanilir.
Hiç yorum yok:
Yorum Gönder