SiteOwner - SiteName MainPage | AboutUs | Jobs | BookRecommendations | Photos| RSS Rss | ContactUs
ContentCategories
ArticleCategories
Ara

Kaynak
FollowingPersons

Lock Anahtar Sözcüğü



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.


İçerik Kategorileri | Bu yazıya henüz yorum yapılmamış. | 20.04.2016 22:23:04

Liskov Substitution Principle (LSP) – Liskov’un Yerine Geçme Prensibi



 

SOLID prensiplerini irdelemeye devam ediyoruz. Bu yazımda, sayın Barbara Liskov hanımın hayatımıza katmış olduğu prensibi anlatacağım. Hali hazırda MIT (Massachusetts Institute of Technology) programlama metodolojileri grup liderliği yapan bu dahi kadın bakın 1988 yılında Data Abstraction and Hierarchy adlı kitabında ne demiş?

 

Aranan yer değiştirme özelliği şöyle tanımlanabilir: T cinsinden parametre alan tüm programlar (fonksiyonlar) P olacak şekilde, S tipinde o1 nesnesi ve T tipinde o2 nesnesi olsun. Eğer o1 ile o2 nesneleri yer değiştirdiğinde P’nin davranışı değişmiyorsa S tipi T tipinin alt tipidir!

Ney? Çok iyi anlayan (hatta anlayan ?? ) varsa beri gelsin! Kendi adıma söyleyeyim; beynimde şiddetli bir karıncalanma hissetmiştim ilk okuduğumda. Hele bir de İngilizcesini okuyunca inanın bana kafayı yiyorsunuz. İşte Barbara ablamızın orijinal cümlesi:

 “What is wanted here is something like the following substitution property:  If for each object o1 of type S there is an object o2 of type T such that for  all programs P defined in terms of T, the behavior of P is unchanged when  o1 is substituted for o2 then S is a subtype of T.”

Ama bakın, bunu resmi olarak 1994 yılında nasıl formüle etmişler (baştan uyarıyorum; bu da matematik ile açıklanmış bir ifade):

q(x) fonksiyonu T tipindeki x nesnesi için kanıtlanabilirdir. O halde T tipinin alt tipi olan S tipindeki y nesnesi için de q(y) fonksiyonu kanıtlanabilir olmalıdır.

Eğer hala bu satırları okuyorsanız (yani “Aha! Şişman Adam sonunda delirdi. Yazık lan” dememişseniz), bu prensibin yazılım tarafında nasıl ifade edileceğini merak ediyorsunuz demektir. Kendi tanımlamalarıma geçmeden önce, bu tarz kavramları ilk kez basite indirgeyerek yazılım dünyasına anlatan Robert Martin’den de bir alıntı yapmamak olmaz.

Robert Martin (namı diğer Bob amca), bakın bu prensibi nasıl anlatıyor:

“Temel (base) sınıfın işaretçisini (pointer) ya da referansını kullanan fonksiyonlar, bu sınıftan türemiş olan (derived) sınıfları da ekstra bilgiye ihtiyaç duymaksızın kullanabilmelidir.” İşte biraz daha yazılım kavramlarıyla bezenmiş bir tanım.

Bakalım ben (namı diğer şişman adam) aynı prensibi nasıl tanımlayacağım?

“Aynı temel sınıftan türeyen tüm sınıflar, birbirlerinin yerine kullanılabilir olmalıdır. Bu yer değiştirme durumunda, sınıfa özel bir istisna kesinlikle oluşmamalıdır.” Tabii bu tanım için yorumlarınızı, bu sayfanın altına bekliyorum.

Elbette bu prensibin anlaşılması için yine bir örnekten faydalanacağız. Diyelim ki, farklı veri kaynakları (SQL, Excel dosyası vs.) ile çalışabilecek bir uygulama geliştiriyorsunuz. Tüm bu veri kaynakları ile “yükleme” ve “kayıt” işlemleri yapabileceğinizi analiz ettiniz ve bu metotları bir abstract sınıfta (ya da interface) tutmaya karar verdiniz. Sonuç olarak şöyle bir abstract sınıf geliştirmiş oldunuz:

Sonra da bu sınıftan türeyen sınıflarınızı aşağıdaki gibi oluşturdunuz.

Sıkıntı yok. Her şey yolunda… Şimdi de veri kaynakları ile işlem yapacak bir sınıfa ihtiyacınız var. Kolları sıvadınız ve aşağıdaki sınıfı oluşturdunuz.

Tamam. Her şey tıkırında. Şu ana dek geliştirmiş olduğunuz tasarım da LSP’ye gayet uyuyor. Ortak bir sınıftan türeyen DatabaseSource ve ExcelFile dosyaları birbirlerinin yerine kullanılabilir durumda. Hadi gelin şimdi işleri biraz karıştıralım.

Projenizi geliştirirken; XML kaynağına da ihtiyaç duydunuz ve yine aynı abstract sınıftan türeyen XMLSource sınıfını oluşturdunuz. Ancak, müşterinin size özellikle vurguladığı bir şey var: “XML dosyaları sadece yüklenebilmeli. Kaydedilmelerini istemiyoruz.” Ne yaparsınız?

Akla hemen iki seçenek geliyor. Bunlardan ilki, XmlSource sınıfında yer alan Save metodunun Exception fırlatması olabilir.

Ancak bu çözümü uygularsanız, DataSourceProcess sınıfında yer alan SaveAll() metodunda; try-catch bloğu kullanmanız gerekecek. Yani, “sınıfa özel istisnai bir durum” şüphesi içinde olacaksınız.

Diğer bir çözüm ise, SaveAll() metodu içerisinde tip kontrolü yapmak olacaktır. Yani metodunuzu şöyle geliştireceksiniz:

Fakat burada da yine “sınıfa özel istisna” yok mu sizce? Bariz bir şekilde tipe özel bir fonksiyon yazmış oluyorsunuz. Yani şu an itibariyle LSP’ye uymayan bir tasarım geliştirmiş bulunmaktasınız.

Peki, nasıl çözeceğiz bu işi?

Aslında bu problemin çözümüne hizmet edecek birkaç yöntem var. Benim burada göstereceğim çözüm, bunların içinden en basit olanı.

Bu yöntemde, özel bir durum oluşmasına sebep olan Save() metodunu ayrı bir abstract sınıf (veya interface) içerisine alacağız. Hadi burada Interface’i tercih edelim:

Böylece abstract DataSource sınıfımda yalnızca GetAllData metodunu bıraktım. Bu durumda ExcelFile ve DatabaseSource sınıflarım hem DataSource sınıfını miras alacak hem de IRecordable interfece’ini uygulayacak (implemente edecek). XMLSource sınıfım ise sadece DatabaseSource sınıfından türeyecek. Yani:

Sonuç olarak; DataSourceProcess sınıfımda SaveAll metodunu tekrar düzenleyerek LSP’ ye uygun bir hale getirebilirim.

Gördüğünüz gibi sevgili dostlarım; SaveAll metodunun son halinde, herhangi bir sınıfa özel bir durum söz konusu değil. IRecordable interface’ini uygulayan her tip birbirinin yerine kullanılabilir durumda.


Tasarım Kalıpları-Design Patterns | Bu yazıya henüz yorum yapılmamış. | 19.04.2016 04:15:33

Open Closed Principle



Bu makalemizde nesne yönelimli tasarım prensiplerinden (OOD Principles) Açık/Kapalı prensibini (Kısaca OCP) ele alacağız. Şimdi durup, günümüzde kullandığımız teknolojik ürünlere bir göz gezdirelim… Tüm ürünler, şu anda kullanmakta olduğumuz son versiyona ulaşıncaya dek ne kadar çok değişikliğe uğradı değil mi? Tamam tamam. Sadece teknolojik ürünler değil, var olan bütün sistemler için geçerli bu söylediğimiz.

All systems change during their life cycles. The must be born in mind when developing systems expected to last longer than the first version.

Bütün sistemler hayatları boyunca değişir. Yazılım geliştirken ilk versiyonunu kullanarak geliştrime yapın.

Yani, biraz klişe olacak ama “değişmeyen tek şey değişimdir”. Peki; madem üretmekte olduğumuz ürünler zamanla değişecek, o zaman biz de bu değişimi “en düşük maliyetli” hale getirmeliyiz değil mi? Bunu sağlamak için bir ürünü, birçok parçanın birleşmesiyle elde ederiz.

Örneğin bir otomobil aslında binlerce parçadan oluşuyor. Tekerlekler, krank mili, motor, akü, depo vesaire… Bu sayede, örneğin yeni bir araba lastiği teknolojisi geliştirildiğinde, hemen var olan bir otomobile uygulanabiliyor. Tek yapmanız gereken arabanızın lastiklerini değiştirmek o kadar. Düşünsenize bir lastiği değiştirmek için arabayı komple değiştirmeniz gerektiğini!

Hadi gelin bu örneği, bir yazılım projesine uyarlayalım. Projenizde kullandığınız nesneler de tıpkı bir makinenin parçaları gibidir. Dolayısı ile bu nesnelerin işlevleri ve sayıları değişebilir. Demek ki öyle bir yapı tasarlamalısınız ki, gelişmeye AÇIK fakat kaynak kodun değiştirilmesine KAPALI olmalı. İşte açık-kapalı prensibinin anahtar cümlesi tam olarak bu. Ama ben yine de bu kavramın mimarı Bertrand Meyer’in cümlesini de buraya yazmayı üstada bir borcum olarak görüyorum: “Yazılım varlıkları (classlar, modüller, fonksiyonlar vs.) gelişime AÇIK, kod değişimine KAPALI olmalıdır.

Eğer bu prensibin teorisine biraz daha eğilmek isterseniz hemen Google’ı açıp “Robert Martin open closed principle” yazın ve efsanenin konu hakkındaki makalesini okuyun.

Artık örnek yapma vakti geldi sanırım. Önce senaryomuzu hazırlayalım. Bir e-ticaret uygulamasında, müşterinin üyelik tipine göre indirim yapmak istiyorsunuz. Buna göre sistemde, premium ve standart olmak üzere iki tür üyelik tipi var. Hadi bakalım; ilk olarak bu sorunumuzu, OCP’ye uymayacak şekilde çözelim.

Hemen, üyelik tiplerini tutacak enum tipimizi oluşturalım:

Şimdi de, müşteriden sorumlu sınıfımızı inşa edelim:

Tamamdır. Son olarak da, bize indirimli fiyatı hesaplayacak sınıfımızı halledelim.

Her şey yolunda gözüküyor değil mi? Projenin çalışmama ihtimali yok. Peki, gelecekte yeni bir üyelik tipi eklenirse ne yapacaksınız! Hah! Gördünüz mü sıkıntıyı şimdi! Projeniz nesnel olarak gelişime açık değil. Çünkü bahsedildiği gibi bir geliştirme yapmak isterseniz, kaynak kodunuzu ciddi bir biçimde değiştirmeniz gerekiyor. Yani UyelikTipi içerisine “Gold” değerini ekledikten sonra bir de SiparisOnay sınıfı içerisindeki FiyatHesapla metoduna yeni bir “case” eklemeniz gerekiyor.

Oysa ne diyordu anahtar cümle: “Yazılım varlıkları (classlar, modüller, fonksiyonlar vs.) gelişime AÇIK, kod değişimine KAPALI olmalıdır.

Eğer bu senaryonun OCP’ye uymasını istiyorsam SiparisOnay sınıfını öyle tasarlamalıyım ki, bir daha asla değiştirmeye gerek kalmasın. Ayrıca yapının geliştirilebilir olması için enum tipinden de kurtulmam gerek!

İşte bu noktada, imdadımıza abstract class yetişiyor. Üyelik tiplerini tek bir çatı altında toplayarak, çok biçimliliğin nimetlerinden faydalanabiliriz. O halde işte çözüm…

Bu değişiklikten sonra SiparisOnay sınıfında yer alan FiyatHesapla metodunu güncellersem, OCP’ye uygun bir mimari elde etmiş olurum.

Şimdi “Gold” üyelik eklemek istediğinizde, tek yapmanız gereken UyelikTipi sınıfından türeyen yeni bir sınıf inşa etmek olacak o kadar!

Sonuç olarak o kilit soruları soralım:

  1. Yeni bir üyelik tipi eklendiğinde, SiparisOnay sınıfında yer alan kodu açıp değiştirmeniz gerekecek mi?

    Cevap: Hayır! SiparisOnay sınıfı kod değiştirmeye KAPALI

  2. İstediğim kadar üyelik tipi ekleyerek projeyi geliştirebilir miyim?

    Cevap: Evet! Tasarımımız, yeni üyelik tipleri ekleyerek gelişmeye AÇIK

İşte sevgili dostlarım. SOLID’in O’su olan Open/Closed Principle’ın olayı bu. Bu arada bu prensibi uygulamak için izlediğim yöntem ise sadece bir yaklaşım. Yani tek yöntem elbette bu değil. Ama sanırım en basiti bu.


Tasarım Kalıpları-Design Patterns | Bu yazıya henüz yorum yapılmamış. | 19.04.2016 02:51:02

Interface nedir



Interface’in kelime anlamı olan “arayüz”e takılırsanız işin içinden çıkamazsınız baştan söyleyeyim :). İçinizden “o zaman adını neden interface koymuşlar” diyor olabilirsiniz. Elbette bunun mantıklı bir sebebi var ve birazdan bu sebebi anlayacaksınız da. Gelin önce basit bir tanımla başlayalım; Interface’ler, geliştirdikleri (iplemente ettikleri) sınıflara yetenek kazandıran yapılardır. Yani “tip” oldukları söylenemez. Peki bir interface’e ne zaman ihtiyaç duyarız? İşte bu sorunun yanıtını verebilmek için, sınıf üyelerinin (metod, olay ve özellik) bir yeteneği temsil edip etmediğini nasıl anlarız sorusuna cevap vermemiz gerekiyor. Haydi bakalım .NET kasabasının meşhur Object Oriented Lokantasına bir uğrayalım.

Söz konusu lokantamızda elbette bir çok nesne mevcut. Ama ben, bu lokantadaki insan nesnesi üzerinde duracağım. Efendim lokantamızdaki insanlar başlangıç olarak ikiye ayrılıyor; çalışanlar ve müşteriler. Davranışsal olarak birbirlerinden farklı olan bu iki nesne için çözümü görebiliyorsunuz sanırım: abstract bir insan sınıfı. Hem çalışan hem de müşteri sınıflarına miras veren bir temel sınıf. Peki, siz bu lokantaya müşteri olarak girdiniz. Masanıza oturdunuz ve kararınızı verdiniz. Şimdi sipariş verme zamanı. Peki… Kime sipariş vereceksiniz? Ya da daha doğrusu, garsonu nasıl tanıyacaksınız? Yakasındaki isimliğinden veya giydiği kıyafetten öyle değil mi? İşte interface! O kıyafet, abstract insan sınıfından türemiş olan çalışan sınıfına garsonluk “yeteneği” kazandırıyor. Ya da başka bir deyişle garson o kıyafeti giyerek; “sipariş al” metodunu iplemente ediyor.

Bu teorik örnek sanıyorum; Interface’e ne zaman ihtiyaç duyacağımız sorusuna cevap veriyor. Ama elbette, kod örneği yapmadan şuradan şuraya göndermiyorum sizi… Örneğimiz, Counter Strike tarzı bir oyun üzerine olacak (aslında Diablo III’e özel bir örnek yapmak niyetindeydim ancak, oradaki silahlar daha karışık). Önce nesne modelimizi oluşturalım:

Oyuncu sınıfımızın basitçe bir görüntüsü. Bu sınıfın “OyuncununSilahi” isimli property’si, geriye Silah sınıfından bir nesne döndürüyor. Silah sınıfı da tahmin edersiniz ki abstract bir sınıf. Çünkü, oyunumuzda hem ateşli silahlar hem de kesici silahlar mevcut ve her ikisi de bambaşka özellikleri olan sınıflar. Öyleyse durum aşağıdaki gibi:

 

Peki, oyuncu sınıfında yer alan “NisanAl” metoduna odaklanalım. Bu metod, oyuncununSilahi özelliğinden dönen nesnenin türüne göre bir davranış sergileyecek. Yani, eğer oyuncunun dürbünlü bir silahı varsa; hedef yakınlaştırılacak, dürbünsüz ise; göz gez arpacık görünümüne geçecek ya da oyuncuda bıçak varsa, bıçağı dik konuma getirecek. Bu noktada, bunu sağlamak için ne yapacağız? Bir an için abstract silah sınıfına “yakınlaştır” isimli bir abstract metod yazdığımı düşünelim. Ama o zaman KesiciSilah sınıfında da “yakınlaştır” metodu oluyor. Burada bariz bir mi mari hata var. Biz bu duruma kısaca WTF (What the folk ?? ) diyoruz.

İşte o zaman anlıyoruz ki, bir silahın dürbünlü olması, o silahın “yeteneği”dir. İşte şimdi gerçekten bir interface’e ihtiyaç duyuyorsunuz. Haydi kolları sıvayalım

Interface’in bir sözleşme olduğunu düşünelim. Bu sözleşmeyi bir sınıfın kabul etmesi demek, sözleşme içerisinde yer alan tüm üyeleri bulunduracağını taahhüt etmek demektir. Bu açıklamaya göre, Interface içerisindeki hiçbir üye access modifier içermemelidir. Çünkü bu üyeler, implemente eden sınıfta public olmak zorundadır. Ayrıca interface üyeleri gövde kodu da içeremezler. Amaçları sadece kalıp oluşturmaktır.

Şimdi dürbünlü bir ateşli silah ekleyelim ve IYakınlastirilabilir interface’ini de iplemente etmesini sağlayalım:

M51 isimli silah, yakınlaştırma “yeteneğine” sahip dürbünlü bir silah oldu gördüğünüz gibi. İşte şimdi, oyuncu sınfımda yer alan “NisanAl” metoduma geri dönebilirim.

Burada gördüğünüz gibi önce OyuncununSilahi özelliğinin Interface’imi implemente edip etmediğini soruyorum. Eğer etmişse Interface’den geçen üyeleri zoom isimli nesneye atıyorum. Ardından da Yakinlastir() metodunu çağırıyorum.

 

… Ve final:

Çıktı:

 

İşte sevgili dostlarım; interface’in kullanımına dair minik bir örnek size… Aman yanlış anlaşılmasın; Interface’in buradaki kullanımı sadece bir pattern. Karşınıza interface’in karşınıza çıkabileceği bir çok senaryo var. Artık onları araştırmak da size düşüyor.


İçerik Kategorileri | Bu yazıya henüz yorum yapılmamış. | 19.04.2016 00:41:37

Yaratımsal Tasarım Kalıpları Creational Design Patterns Factory Method



Yaratımsal (creational) tasarım desenleri, karmaşık bir mimaride sınıftan bir örnek (instance) üretirken kullanılan desenlerdir. Tasarım desenleri yazımda da belirttiğim gibi, desenler; “sık karşılaşılan sorunların bir çözümüdür”. Öyleyse, bir tasarım desenini anlamanın en iyi yolu öncelikli olarak problemle karşılaşmaktır.

 

Öncelikle, kategorinin adını açıklayarak başlayalım işe. Yaratımsal (creational) tasarım desenleri, karmaşık bir mimaride sınıftan bir örnek (instance) üretirken kullanılan desenlerdir. Tasarım desenleri yazımda da belirttiğim gibi, desenler; “sık karşılaşılan sorunların bir çözümüdür”. Öyleyse, bir tasarım desenini anlamanın en iyi yolu öncelikli olarak problemle karşılaşmaktır.

 

Dilerseniz factory method tasarım deseninin çözmüş olduğu problemi, günlük hayattan bir örnekle görelim (tabii ki). Diyelim ki yeni bir eve taşınacaksınız ve oturma grubunuzu da o eve uygun olacak şekilde seçmek istiyorsunuz. Mobilyacıya gittiniz ve bir de baktınız ki farklı büyüklüklerde ve fiyatlarda birçok koltuk çeşidi mevcut. İşte problem! Seçimi hangi kritere göre yapacaksınız? Bu durumda hemen aklınıza belirlemeniz gereken iki parametre gelmiş olmalı. Bunlardan birincisi bütçeniz diğeri de evin salonunun boyutları olacaktır. Bu iki parametre ile mobilyacıya danıştığınızda istediğiniz kriterlere uygun bir mobilyayı daha rahat bir biçimde bulabilirsiniz.

İşte bu örnekte; mobilyacınız, sizin için uygun olan mobilyayı sağlayan Factory metodunu içeren sınıftır.

Dolayısı ile, şimdi teknik bir tanım yapabiliriz. Factory Method deseninin ana amacı, “genişletilebilirlik” tir. Birbirinden yapısal olarak farklı ancak aynı zamanda birçok karakteristik özelliği ortak olan nesnelerin yönetimi, oluşturma kıstaslarının belirlenmesi ve yaratılması için Factory Metodu kullanılır.

Şimdi söz konusu deseni, teknik bir örnekle açığa kavuşturalım.

İlk olarak, olaya çok basit yaklaşalım. Diyelim ki, bir ev dekorasyon simülatörü üretiyorsunuz ve kullanıcının seçimlerine göre üretilen mobilyaları belirtilen alana yerleştirmek istiyorsunuz. Her mobilyanın standart olan özelliklerini (en, boy, genişlik, şekil, renk vs.) bir Interface’de tutabilir ve tüm mobilyaları bu Interface’den implemente edebilirsiniz değil mi?

Bu durumda size ihtiyaç duyduğunuz mobilya nesnesini üretebilecek bir sınıfa gereksiniminiz var demektir. O zaman gelin bu sınıfı oluşturup, “oluşturma” sorunumuzu çözelim:


Gördüğünüz gibi, Factory metodum bir parametre alıyor (enum) ve bu parametrenin değerine göre istenen nesneyi üretip döndürüyor. İşte Factory metot tasarım deseninin en sade ve basit örneği bu.

Şimdi gelin bu çözümü daha farklı bir örnekte yeniden inceleyelim.

Örneğimizde bir blog sistemi ya da CMS (Content Management System) projesine giriştiğimizi varsayalım. Böyle bir projede olmazsa olmaz diyebileceğimiz konulardan biri kullanıcı rolleri ve bu rollerin izinleridir. Söz gelimi yönetici rolündeki bir kullanıcının yetkileri ile editör ya da normal kullanıcıların yetkileri birbirlerinden farklıdır. Buradaki roller sistemin ihtiyaçlarına göre çoğalabilecek durumdalar öyle değil mi?

Demek ki böyle bir mimaride (OCP prensibine de hatırlatarak), abstract bir Izin sınıfı oluşturur ve tüm izinleri bu sınıftan türetirsem anlamlı bir adım atmış olurum:


Tamamdır. Şimdi, roller kendi içinde bu izinlerin bir koleksiyonunu barındırması gerektiğini biliyoruz. Ayrıca birden fazla rol olacağına göre benzer bir mimariyi rol için de kurgulayabiliriz. İşte burada kullanacağımız abstract rol sınıfında, role göre yetki oluşturulmasını sağlayacak abstract bir “izinleriOlustur” metodu oluşturacağız. İşte bu metot, bizim factory metodumuz olacak!


Gelelim kod tarafına. Önce Izin sınıfının kodlarına bakalım:


Ardından da Rol abstract sınıfını görelim:


Şimdi sevgili dostlar; her rolün bu factory metodunu nasıl ezdiklerine bakalım:


 

Şimdi sıra geldi Main metodunu yazma kısmına:


Son olarak da çıktımıza bir bakalım:


Gördüğünüz gibi dostlar, bir nesneye (rol) bağlı olan (dependency) ortak nesneleri (izin) üretebilmek için Factory metot tasarım desenini kullandım. Bu noktada Factory metodun kurallarını özetleyelim:

  • Metot, bir nesne oluşturmalı
  • Metot, abstract class ya da interface döndürmeli
  • Bu abstract class veya Interface’ler başka sınıflar tarafından implemente edilmeli.

Evet sevgili dostlar; tasarım desenleri serisinin ilk desenini böylece incelemiş olduk. Bir sonraki DP makalesinde görüşmek üzere…

Kendinize özgüvenle bakın.

 


Tasarım Kalıpları-Design Patterns | Bu yazıya henüz yorum yapılmamış. | 19.04.2016 00:16:35

1 2
MainPage | AboutUs | Jobs | BookRecommendations | Photos | Rss| ContactUs
SiteOwner Copyright
design Creator