Tasarim Desenleri - Iterator Patterns

27. Ekim 2011 09:42 by hasantatarli in Tasarım Desenleri  //  Tags: , , ,   //   Yorumlar (0)



Merhabalar, Bir önceki makalemizde Davranışsal Tasarım Desenlerinden State Pattern üzerinde durmuştuk. Şimdi yine Davranışsal Tasarım Desenlerinden Iterator Pattern(öteleyici tasarım deseni) üzerinde durmaya çalışacağım. Öncelikle Iterator Design Pattern(Yineliyici Tasarım Kalıbı) nedir bunu incelemekte fayda var. Iterator Pattern, dizilerde veya koleksiyonlarda nesnelerin elemanlarına ulaşılması, bu dizilerde veya koleksiyonlar içerisinde dolaşılması, dolaşılması sırasında işlem durursa nerede durduğunun tutulması, tekrar devam edilmesi gerektiğinde nasıl devam edeceğini bilmesi ve bir sonraki nesnenin hangisi olacağının bilinmesi gibi durumları yerine getiren bir tasarım kalıbıdır. Bu kalıbı aslında farkında olmadan kullanmaktayız fakat bu kalıbın Itarator tasarım kalıbı olduğunun çoğu zaman  farkında bile değiliz. Nasıl mı kullanıyoruz?  Koleksiyonlar içerisinde dolaşmak için for,while, foreach gibi kullandığımız yapıların temelinde bu tasarım kalıbı kullanılmaktadır. Bu şekilde bir list içerisinde for, foreach veya while gibi yapılarla dönemk istdiğimizde bizim yerimize bu kalıpları otomatik olarak kullanmış olmaktayız. Iterator Pattern, genel olarak incelendiğinde aşağıdaki UML diyagramına sahip olan bir yapı mevcuttur. Iterator arayüzü içerisinde bu arayüzden türeyen sınıfların kullanacağı ve sorumlu olduğu operasyonları bildirmektedir. Yukarıda da belirttiğimiz gibi işlem içerisinde hangi aşamada olduğunu ve hangi nesneyi kullandığını gösteren CurrentItem adında bir metod veya property vardır. Bir sonraki aşamaya geçmek için MoveNext metodu, daha sonra herhangi bir nesne olup olmadığını kontrol etmek için IsContinue metodu vardır. First metoduyla Iteration’ın başlayacağı nesye gönderen metod bulunmaktadır. İstemci Aggregate nesnesini kullanıp, bu nesne içerisinde dolaşmak için Iterator’den yardım almaktadır. Yine Aggregate’ten türetilen bir ConcreteAggregate sınıfı, Iterator sınıfından türetilen ConcreteIterator sınıfı bulunmaktadır. Şimdi bir örnekle buraya kadar bahsettiklerimizi daha anlaşılır bir hale getirelim. Employee tipinde nesnelerin oluşturduğu bir nesne kümesi(List<Employee>) içerisinde Employee üyeleri arasında Itarator Patter yardımıyla dolaşarak Iterator Pattern in yapısı öğrenmeye çalışacağız. Örnek Kodlarımız: // Employee Sınıfı public class Employee { // Fields private int _employeeId; private string _name; private decimal _salary; // Properties public int EmployeeId { get { return _employeeId; } set { _employeeId = value; } } public string Name { get { return _name; } set { _name = value; } } public decimal Salary { get { return _salary; } set { _salary = value; } } // Methods public override string ToString() { return string.Format("{0}{1}{2}", EmployeeId.ToString(), Name, Salary.ToString("C2")); } } // Iterator // IEmployeeIterator arayüzü // Nesne içerisinde yapılmasını tasarladığımız işlemler için gerekli arayüz public interface IEmployeeIterator { Employee First(); Employee MoveNext(); bool IsContinue { get; } Employee Current { get; } } // IEmployeeCollection arayüzü public interface IEmployeeCollection { IEmployeeIterator GetIterator(); } // ConcreteAggregate // IEmployeeCollection arayüzünden türeyen EmployeeCollection sınıfı public class EmployeeCollection : IEmployeeCollection { // Employee Listini saklamak için oluşturulan generic List<T> kolleksiyon private List<Employee> list = new List<Employee>(); // çalışanların sayısını veren özellik public int EmployeeCount { get { return list.Count; } } // çalışanların eklenmesi ve eklenenlerin okunması için kullanılan indexleyici public Employee this[int index] { get { return list[index]; } set { list.Add(value); } } // Iterator nesnesini örnekler public IEmployeeIterator GetIterator() { //Iterator Nesnesi örneklenirken o andaki EmployeeCollection nesnesi referans olarak örneklenir ve böylecehangi nesneyi dolaşacağını bilecektir. return new EmployeeIterator(this); } } // ConcreteIterator // IEmployeeIterator arayüzünden türeyen EmployeeIterator sınıfı public class EmployeeIterator : IEmployeeIterator { //Iterator Nesnesi, çalışma zamanında hangi nesneyi dolaşacağını bilmesi gerekir. private EmployeeCollection _employeeCol; private int _currentIndex = 0; // StepSize ile Nesne bütünü arasında kaçar kaçar dolaşacağını belirtir(birer birer, üçer üçer gibi) verilecek parametreyle belirlenir. public int StepSize { get; set; } public EmployeeIterator(EmployeeCollection employeeCollection) { _employeeCol = employeeCollection; } // ilk elemana gidilen metod public Employee First() { _currentIndex = 0; return _employeeCol[0]; } // Bir sonraki metoda götüren metod public Employee MoveNext() { _currentIndex += StepSize; if (IsContinue) { return _employeeCol[_currentIndex]; } else { return null; } } // O anki elemanı döndürür public Employee Current { get { return _employeeCol[_currentIndex]; } } //Bir sonraki employee nin olup olmadığını kontrol eder public bool IsContinue { get { return _currentIndex < _employeeCol.EmployeeCount; } } } class Program { static void Main(string[] args) { EmployeeCollection employees = new EmployeeCollection(); employees[0] = new Employee { EmployeeId = 1, Name = "Hasan Yalçın ", Salary = 1500M }; employees[1] = new Employee { EmployeeId = 2, Name = "Kamil Eker ", Salary = 2000M }; employees[2] = new Employee { EmployeeId = 3, Name = "Cemil Taşdöğen ", Salary = 1750M }; // Itarator Nesnesi employees adlı koleksiyonu kullanmak için oluşuturulur. EmployeeIterator emIterator = new EmployeeIterator(employees); // Adım sayısı belirlenir. emIterator.StepSize = 1; for (Employee employee = emIterator.First(); emIterator.IsContinue; employee = emIterator.MoveNext()) { Console.WriteLine(employee.ToString()); } } } Sonuç: Faydalı olması dileğiyle.

Tasarim Desenleri - Design Pattern

20. Ekim 2011 13:48 by hasantatarli in Tasarım Desenleri  //  Tags: , , , ,   //   Yorumlar (0)



Merhabalar, Bugün sizlere Design Patterns(Tasarım Desenleri) konusundan State Pattern'i(Durum Desenlerini) anlatmaya çalışacağım. Fakat öncelikle Bu Tasarım Desenleri nedir, ne işe yarar, yenilir mi, içilir mi ondan bahsetmek istiyorum. Tasarım Desenleri, yazılım geliştirmede sürekli karşılaştığımız sorunları genel olarak ele alarak bu tarz sorunların aşılmasında hızlı, başarılı ve esnek çözümler sağlayan hazır kalıplardır. Bu tasarımların hemen hemen her birini uygulayabileceğimiz alanlar olduğu gibi bir problemin çözümünde birden fazla kalıpların kullanıldığı da olmaktadır. Tasarım Desenleri dediğimizde aklımıza genellikle GoF(Gang of Four) tasarım desenleri gelmektedir ki bunlar 3 grup altında 23 tane tasarım desenidir. Fakat bunların dışında da tasarım desenleri bulunmaktadır. GoF Tasarım Desenleri Grupları: 1- Creational Patterns (Kurucu Desenler) (Şuradan Creational Patternsle alakalı yazıları bulabilirsiniz.)2- Structural Patterns (Yapısal Desenler)3- Behavioral Patterns (Davranışsal Desenler) Benim size anlatacağım State Pattern 3. gruba yani Behavioral Patterns içerisine girmektedir. State Pattern kullanım açısından çok sık kullandığımız bir pattern değildir fakat orta seviyelerde bir kullanım alanı vardır. Bu tasarımın önemli özelliklerinden bir tanesi duruma bağlı değişiklik gösteren kurgularda iç içe "if/else" ve "swicth" yapısını kullanmayı en aza düşürmektedir. Böylece "if/else" lerin içersinde boğuşmaktan kurtulabilirsiniz. Bu kadar konuşmadan sonra bir örnekle olayın daha iyi anlaşılması sağlayalım: Örnek: Bir okul düşünün bu okula giren bütün öğrenciler ücretli olarak başlıyorlar fakat daha sonra gösterdikleri başarılara göre burs kazanıyorlar. Burada öğrencinin burs durumunda değişiklik oluyor. Şimdi bunu UML diagramla gösterelim: Örnek UML Diagram: Örnek C# Kodu : /* IUcretDurumu.cs */ public interface IUcretDurumu { // interface içerisinde olan metodlarımız //UcretHesapla() öğrencinin ücretinin hesaplanması için void UcretHesapla(); // UcretOde() öğrencinin ödemesi gereken ücreti ödeyecek void UcretOde(); } /* Ucret.cs */ public class Ucret { public IUcretDurumu ucretDurumu; // Ucret classının instance’ı alındığında default olarak Normal Ücreti // hesaplayacak public Ucret() { ucretDurumu = new NormalUcret(); } public void UcretOde() { ucretDurumu.UcretOde(); } public void UcretHesapla() { ucretDurumu.UcretHesapla(); } // IucretDurumu türünden bir değişken alıp öğrencinin durumunu gelen değişkene // göre değiştirecek public void durumDegistir(IUcretDurumu ucretDurumu) { this.ucretDurumu = ucretDurumu; } } /*NormalUcret.cs*/ public class NormalUcret : IUcretDurumu { public void UcretHesapla() { Console.WriteLine("Normal Öğrencinin Ücreti Hesaplandı."); } public void UcretOde() { Console.WriteLine("Normal Ogrencinin Ucreti Ödendi."); } } /*BursUcret.cs*/ public class BursUcret : IUcretDurumu { public void UcretHesapla() { Console.WriteLine("%50 Burslu Öğrencinin Ücreti Hesaplandı."); } public void UcretOde() { Console.WriteLine("%50 Burslu Ogrencinin Ucreti Ödendi."); } } /*Ogrenci.cs*/ Public static void Main(string[] args) { // oluşturulan ücret varsayılan olarak 'normal' durumda. Ucret ucret = new Ucret(); ucret.UcretHesapla(); ucret.UcretOde(); // Öğrenci Burs durumuna göre yeni burslu durumuna geçiriliyor. ucret.durumDegistir(new BursUcret()); // Öğrencinin durumu değiştiği için ücrethesaplaması ve öcret ödemesi de değişecek ucret.UcretHesapla(); ucret.UcretOde(); }