Yazılım tasarımında sürekli karşılaşılan genel sorunlara esnek, yeniden kullanılabilir, başarılı çözümler getiren bir takım hazır kalıplardır. Nesneye dayalı programlamada, tasarım desenleri sınıf ve nesneler arasındaki ilişkilerin en iyi şekilde nasıl olmaları gerektiğini açıklayan yöntemlerdir.
Tasarım kalıpları daha önce sınanmış, ispatlanmış ve yararı görülmüş yazılım yöntemleri önerdiği için geliştirme sürecini hızlandırır. Yeniden kullanılabilir, esnek çözümler yazılımın büyümesini, genişlemesini kolaylaştırır. Tasarım kalıplarını bilen, yazılımcı ve yazılım mimarları için kod okunabilirliği yüksek olur. Ekip içerisinde tasarım kalıplarıyla ortak dil kullanılmış olur.
Tasarım kalıpları:
- Creational Patterns (Oluşturucu Tasarım Kalıpları): yazılım nesnelerinin nasıl oluşturulacağı hakkında genel olarak öneriler sunarak kullandığı esnek yapı sayesinde daha önceden belirlenen durumlara bağlı olarak gerekli nesneleri yaratır. Nesnelerin uygun ve verimli bir şekilde yaratılma yollarıyla ilgilenirler. Nesne yaratma sorumluluklarını, farklı sınıf düzenlerinde soyutlayarak yaparlar.
- Abstract Factory: yaratılma sorumluluklarının çeşitli sınıf hiyerarşileri ile sağlandığı bir tasarım kalıbıdır. İstemci sınıf, çeşitli kategorideki sınıflara ihtiyaç duyar. Bu sınıflar, sistemde alt/üst sınıf hiyerarşileri şeklinde bulunurlar. Abstract factory tasarım kalıbı bu karmaşık ve farklı hiyerarşideki sınıfların yaratılma sorumluluğunu çeşitli fabrika sınıflarına verir. Karşımıza aşağıdaki sorunlar çıktıysa büyük ihtimal ile Abstract Factory tasarım kalıbına ihtiyacımız vardır.
- Çalıştığı platformdan bağımsız bir uygulama geliştirmek istiyoruz.
- Benzer özelliklere sahip objelerimiz var.
- Benzer objelerin yaratılma mantığını, objelerin yaratılacağı sınıfları tek tek belirtmeden interface bağlı gruplamak istiyoruz.
- Builder: tasarım kalıbı ile bir nesneyi, bir sınıfı, aşama aşama farklı özellikleri ile oluşturabiliriz.
- Kompleks yapıda bir objemiz var.
- Objeyi oluşturmak için belirli bir sırayı takip etmemiz gerekli.
- Factory Method: tasarım kalıbı, nesne yaratma sorumluluğunun bir yordama verilmesidir. Yaratılan nesne, bir sınıf hiyerarşisindeki alt sınıflardan biridir. Hangi alt sınıfın yaratılacağı kararı factory method içinde verilir.
- Oluşturacağımız objenin tipini önceden belirtmek istemiyoruz.
- Oluşturulacak objenin tipi runtime değişiklik gösterecek ise.
- Prototype: var olan bir nesneden, kopyalama yöntemi ile yeni nesne yaratmak için bu tasarım kalıbı kullanılır. Nesne yaratmak için “new” operatörü kullanılmaz. Yazılım dillerindeki “clone” gibi, nesne kopyalama yordamlarından faydalanılır.
- Bir objenin özelliklerine sahip olan aynı tipte bir obje yaratmak istiyoruz.
- Singleton: tasarım kalıbında, bir sınıfın sistem içinde yalnızca bir tane nesnesi oluşturulabilir. Tek bir arayüz sunularak, bu nesneye yalnızca buradan erişim sağlanabilir.
- Yalnızca 1 objeye ihtiyacımız var
- Objeye her sınıftan erişebilmemiz gerekli
- Abstract Factory: yaratılma sorumluluklarının çeşitli sınıf hiyerarşileri ile sağlandığı bir tasarım kalıbıdır. İstemci sınıf, çeşitli kategorideki sınıflara ihtiyaç duyar. Bu sınıflar, sistemde alt/üst sınıf hiyerarşileri şeklinde bulunurlar. Abstract factory tasarım kalıbı bu karmaşık ve farklı hiyerarşideki sınıfların yaratılma sorumluluğunu çeşitli fabrika sınıflarına verir. Karşımıza aşağıdaki sorunlar çıktıysa büyük ihtimal ile Abstract Factory tasarım kalıbına ihtiyacımız vardır.
- Structural Patterns (Yapısal Kalıplar): yaratım ve davranış kalıpları ile beraber tasarım kalıplarını oluşturan modellerden biridir. Amaçları itibariyle yapısal kalıplar, sınıflar ve nesnelerin birleştirilerek daha geniş yazılım gruplarının kurulmasına olanak sağlayan öneriler sunar.
- Adapter: farklı sınıfları olan nesnelerin birlikte çalışmasına izin veren yapısal bir tasarım kalıbıdır.
- Birbirleriyle uyumsuz sınıfları çalışabilir hale getirmek istiyoruz.
- Composite: tasarım kalıbının amacı, nesneleri ağaç yapısına göre düzenleyerek, ağaç yapısındaki alt üst ilişkisini kurmaktır. Bu tasarım kalıbına göre, ağaç yapısındaki üst ve alt nesneler aynı arayüz sınıfından türeyerek, birbirlerine benzerler.
- Basit objelerden ve bu basit objeleri barındıran kompleks objelerden oluşan bir yapı istiyoruz.
- Decorator: tasarım kalıbı, nesneye ek özellikler eklemek için kullanılır. Nesnenin özeliklerini arttırmak için, temel nesneden türetilip de, yeni nesneler yaratılmasına gerek yoktur. Yani bu desen, bir nesneye alt sınıflar yaratılmaksızın, dinamik olarak yeni özellikler kazandırmak için kullanılır.
- Objelere yeni özellik kazandırmak istiyoruz.
- Facade: tasarım kalıbı, sistemin detaylarını saklayarak, istemcinin dışarıdan sisteme ulaşabilmesi için tek bir ön yüz sunar. Sistemdeki alt sınıflara, bu ön yüz sınıfı ile ulaşılır.
- Birçok sistemi bir üst sistemde toplayarak bu alt sistemlere erişim kolaylığı sağlamak istiyoruz.
- Fly Weight: tasarım kalıbı çok sayıda nesnenin sistemde olduğu durumlarda, nesne sayısının sistemde problemlere neden olmaması için kullanılan tasarım desenidir.
- Birbirine benzer çok sayıda obje oluşturmak istemiyoruz.
- Proxy: yaratılması pahalı bir çok işlem yapan bir nesneyi taklit eden bir başka nesnenin kullanılmasıdır.
- Bol bol kaynak tüketen bir objeye sahibiz.
- Bu sebeple objeyi kullanmadan önce initialize etmek istemiyoruz.
- Adapter: farklı sınıfları olan nesnelerin birlikte çalışmasına izin veren yapısal bir tasarım kalıbıdır.
- Behavioral Patterns (Davranışsal Kalıplar): Belirli görevlerin bu işleri yapmak üzere tasarlanmış nesnelere gönderilmesi ve geri dönen sonuçların işlenmesi davranışsal tasarım kalıpları içerisinde yapılan bir işlemdir.
- Chain of Responsibility: tasarım deseni, bir dizi işlev sınıflarıyla, bu sınıfların işlevlerini başlatmak için gereken komut sınıflarından oluşur. İşlev sınıfları, ne tür işler yapacağını kendi bünyesinde tutar, ayrıca dizideki diğer bir işlev sınıfının ne olacağını da belirler. Bir işlemin, belli miktarda işlevlerden sırayla geçmesi gerektiğinde bu tasarım deseni kullanılabilir.
- Bir istek sonucu oluşacak etkiyi gerçekleştirecek yapıların birbirlerine bağlanmasıyla oluşur.
- Birçok yapıdan yalnıza biri yapılacak işi gerçekleştirir.
- Atm den çekilen paraya göre banknot vermesi gibi.
- Command: nesneler bir işlevi ve bu işlev için gerekli değiştirgeleri içerirler. Dışarıdan bu nesneler tetiklenerek bazı işlemler gerçekleştirilir. Bu tasarım deseniyle, işlemi tetikleyecek nesneler ile işlemi yapan nesneler birbirlerinden ayrılmış olur. İşlemi yapacak nesneler birden fazla olabilir ve bunlar koleksiyonlarda saklanabilir. Bu nesnelerin hepsi birden sırayla çalıştırılabilir, böylece istenen fonksiyon, birden fazla işlevin çalışmasıyla gerçekleştirilmiş olur. Yeni işlevler istendiğinde, yeni komut nesneleri de kolayca eklenebilir.
- Yapılacak bir çağrı için tüm bilgiyi bir objede tutmak istiyoruz.
- Alakalı komut istenen zamanda sıralı işlemler içeren bir batch şeklinde çağrılabilir.
- Interpreter: işlemlerin nesne haline getirilip başka bir nesne(invoker) üzerinden tetiklendiği bir tasarım desenidir.
- Belirli kural kümelerini bir gramerle ifade etmek istiyoruz.
- Bu kural kümelerini anlamlı ifadeye çeviren bir tercüman ihtiyacı duyuyoruz.
- Müziğin notayla ifade edilmesi
- SQL ifadeleri
- Iterator: nesne koleksiyonlarının elemanlarını belirlenen kurallara göre elde edilmesini düzenler.
- Sırasıyla dolaşmak istediğimiz bir araya gelmiş obje kümemiz var.
- Amacımız yalnızca sırayla dolaşmak, nasıl dolaştığımızın detaylarını bilmemize gerek yok.
- Mediator: sınıfların sayısı arttıkça, aralarındaki bağımlılıklar artar, uygulamanın bakımı ve değiştirilmesi zorlaşır. Mediator tasarım kalıbı, bu sınıflar arasındaki bağımlılıkları azaltmak ve aralarındaki iletişimi kolaylaştırmak için kullanılır.
- Sınıfların birbirleriyle direkt konuşmasını istemiyoruz ki sınıflar arası dependency oluşturmak durumunda kalmayalım.
- Hava trafik kontrol gibi
- Memento: nesnenin durumunu saklayıp, daha sonra bu duruma tekrar geri dönebilmesini sağlayan tasarım desenidir.
- Objenin bir iç durumuna ait değerler için checkpoint oluşturmak istiyoruz.
- Oyun karakterimiz öldüğünde en son kaydedilen checkpoint e dönmek istiyoruz.
- Observer: nesnenin durumlarında değişiklik olduğunda, bu değişikliklerden haberdar olmak isteyen diğer nesnelere haber verilmesi gerektiği durumlarda bu tasarım deseni kullanılır.
- Bir objeyle alakalı değişim olduğu zaman, bu değişimden belirli objeleri haberdar etmeyi amaçlıyoruz.
- Dinamik biçimde değişikliğin takibini yapacak objeleri ekleyip çıkartmak istiyoruz.
- State: nesnenin durumu değiştiğinde, davranışı da değişiyorsa, yani nesneler farklı durumlarda, farklı davranışlar gösteriyorsa, durum tasarım deseni kullanılabilir.
- Objenin davranış biçimini kendine ait olan belirli durumlara göre dinamik biçimde değiştirmesini istiyoruz.
- Strategy: bir işlem için farklı yöntemlerin uygulanabilir olduğu durumlarda, bu yöntemi kullanacak olan nesne, hangi yöntemin uygulanacağını seçer. Çünkü bu içerik nesnesi, yöntemleri belirleyen üst sınıfı içerir. Farklı yöntem veya strateji alt sınıfları da, bu üst sınıftan türerler.
- Bir sınıfa ait davranışlar dinamik olarak değişebiliyorsa bu davranışlara algoritmaları ayrıştırarak saklamamız mantıklı olacaktır.
- Böylece runtime’da davranışları karışıklık yaşamadan değiştirebilir hale getireceğiz.
- Template Method: bir algoritmanın adımlarının abstract sınıfta tanımlanarak farklı adımların concrete sınıflarında overwrite edilip çalıştırılmasını düzenler.
- Bir sınıfa ait birbirine benzer yapıya sahip algoritmalar da yalnızca bazı adımları değiştirmek istiyoruz.
- Visitor: tasarım deseni, çok sayıda ve farklı tipteki nesneler üzerinde işlem yapabilmek amacıyla kullanılır. İşlem yapılacak nesnelerde herhangi bir değişiklik yapılmaz. İşlemi ziyaretçi nesneleri yapar. Eğer sisteme yeni nesneler eklenmiyor, fakat sık sık yeni işlemlerin eklenmesi gerekiyorsa bu tasarım deseni kullanılabilir.
- Sınıflarımıza yeni bir metot eklemek istiyoruz.
- Eklenmesi gereken sınıflara tek tek manuel biçimde ekleyip kod bakımını zorlaştırmak istemiyoruz.
- Birden fazla sınıfın implement ettiği interface’e ekleyip tek tek sınıflarda implementasyonu gerçekleştirmek istemiyoruz.
- Chain of Responsibility: tasarım deseni, bir dizi işlev sınıflarıyla, bu sınıfların işlevlerini başlatmak için gereken komut sınıflarından oluşur. İşlev sınıfları, ne tür işler yapacağını kendi bünyesinde tutar, ayrıca dizideki diğer bir işlev sınıfının ne olacağını da belirler. Bir işlemin, belli miktarda işlevlerden sırayla geçmesi gerektiğinde bu tasarım deseni kullanılabilir.
Design patterns ile ilgili sunumun pdf dosyası için TIKLAYINIZ.
Design patterns ile ilgili link için TIKLAYINIZ.
Desing patterns java kodları için TIKLAYINIZ.
Desing patterns ile ilgili Java kodu ile yazılmış örnekleri indirmek için TIKLAYINIZ.
İyi çalışmalar 🙂