Merhaba arkadaşlar,

Uzun bir bayram arasından sonra Behavioral(Davranışsal) tasarım kalıpları konumuza kaldığımız yerden hızla devam ediyor olacağız. 🙂

Yine kullanım oranı oldukça sık görülen bir tasarım deseni olan Template Method desenini inceleyeceğiz.

Template Method deseni için:

Şablon bir algoritmamızın soyut(abstract) bir sınıfa implemente edilip, sorumlulukların alt sınıflara dağıtılması işlemidir diyebiliriz.

Bu sayede bize katacağı avantajları ele aldığımızda ise:

  • Kod tekrarının önüne geçilerek, tekrar kullanılabilirliği arttırır
  • Maintenance işlemi olarakta, şablon algoritma üzerinde gerçekleştirilerek bir değişimi tek bir noktadan yapılabilmesini sağlamaktadır

UML şeması aşağıdaki gibidir:

AbstractClass: Şablon algoritmamızın tanımlanacağı soyut sınıf.
ConcreteClass: Şablon algoritmanın adımlarını gerçekleştirecek olan gerçek sınıfımız.

Bir örnek üzerinde kullanımına bir bakalım.

Örneğimizde basit bir Configuration Reader kütüphanesi oluşturalım. Bu kütüphane ister App.Config istersede xml dosyası üzerinden vereceğimiz bir key doğrultusunda bize değerini okuyup getirebilecek. Buradaki şablon algoritmamız ise Read işlemi olsun.

    public abstract class ConfigurationBase
    {
        public object Read(string key)
        {
            // Şablon algoritma isteketi üzerinde istenilen işleri yaptırabilirsiniz. Caching işlemleri, Validation vs.
            object val = GetValue(key); // Şablon algoritma uygulanır.

            return val;
        }

        // Alt sınıfların ilgili işlemi uygulayabilmesi için soyutluyoruz.
        protected abstract object GetValue(string key);
    }

ConfigurationBase soyut sınıfımızı tanımladık ve şablon algoritma iskeletimiz olan Read metotunu implemente ettik. Read metotu içerisinde ise ilgili alt sınıfların kendilerine özel sorumluluklarda ilgili metotu override edebilmeleri için GetValue isminde dışarıya kapalı bir abstract metot tanımladık.

Şimdi sıra geldi gerçekleyecek olan sınıfımıza.

    public class AppConfigReader : ConfigurationBase
    {
        protected override object GetValue(string key)
        {
            return System.Configuration.ConfigurationManager.AppSettings[key];
        }
    }

AppConfigReader sınıfında ConfigurationBase soyut sınıfını miras alarak yine soyut olarak tanımladığımız GetValue metotunun override işlemini gerçekleştirdi ve kendi sorumluluğunda olan App.Config üzerinden okuma işlemini gerçekleştirdi.

Bunun gibi gerçekleyen sınıfları ilgili iş kurallarınız gereği sizde çoğaltabilirsiniz. Xml dosyası üzerinden okuma, veritabanı üzerinden okuma gibi.

Kullanımına geçmeden önce ilgili gerçekleyen sınıflarımızın üretiminden sorumlu olacak ilgili factory sınıfını yazalım 🙂 Bir sonraki makale konumda ise Factory Method tasarım deseni hakkında detaylı bilgiyi vereceğim.

    public class ConfigurationFactory
    {
        // Istem dışı bir örnekleme alınamaması için constructor'ı private yapıyoruz.
        private ConfigurationFactory()
        {

        }

        // Tek bir örneğinin olabilmesi için Lazy sınıfı aracılığı ile Singleton tasarım desenini uyguluyoruz.
        private readonly static Lazy<ConfigurationFactory> _instance = new Lazy<ConfigurationFactory>(() => new ConfigurationFactory());
        public static ConfigurationFactory getInstance
        {
            get
            {
                return _instance.Value;
            }
        }

        public ConfigurationBase CreateReader(string readerName)
        {
            // İlgili ürütme işlemini if-else bloglarından kurtarabilmek için bir kaç küçük
            // reflection kodu yazarak aşmak mümkün. Fakat 1-2 sınıf için uğraşmaya değmez. :)
            if (readerName == "AppConfigReader")
            {
                return new AppConfigReader();
            }

            return null;
        }
    }

ConfigurationFactory sınıfınıda Singleton tasarım deseninide uygulayarak geliştirdik. Artık gerçek sınıflarımızın üretiminden de sorumlu olacak tek bir sınıfımız var.

Her şey hazır olduğuna göre şimdi kullanımına bir göz atalım:

        static void Main(string[] args)
        {
            ConfigurationBase appConfigReader = ConfigurationFactory.getInstance.CreateReader("AppConfigReader");

            Console.WriteLine(appConfigReader.Read("NeredenGeliyorsun"));
            Console.ReadLine();
        }

Örneğimizde şablon algoritmamızı ConfigurationBase sınıfına implemente ederek Read işlemini ilgili alt sınıflara bıraktık. Bu sayede şablon algoritmamız üzerinde tek bir noktadan yani ConfigurationBase üzerinden istediğimiz değişikliği yapabilir bir hale getirdik. ConfigurationFactory sınıfı aracılığı ise üretim işlerini tek bir sınıfa yükledik.

Ekran çıktısı aşağıdaki gibidir:

 

Gökhan Gökalp

View Comments

Recent Posts

Containerized Uygulamaların Supply Chain’ini Güvence Altına Alarak Güvenlik Risklerini Azaltma (Güvenlik Taraması, SBOM’lar, Artifact’lerin İmzalanması ve Doğrulanması) – Bölüm 1

{:tr}Bildiğimiz gibi modern yazılım geliştirme ortamında containerization'ın benimsenmesi, uygulamaların oluşturulma ve dağıtılma şekillerini oldukça değiştirdi.…

8 ay ago

Identity & Access Management İşlemlerini Azure AD B2C ile .NET Ortamında Gerçekleştirmek

{:tr}Bildiğimiz gibi bir ürün geliştirirken olabildiğince farklı cloud çözümlerinden faydalanmak, harcanacak zaman ve karmaşıklığın yanı…

12 ay ago

Azure Service Bus Kullanarak Microservice’lerde Event’ler Nasıl Sıralanır (FIFO Consumers)

{:tr}Bazen bazı senaryolar vardır karmaşıklığını veya eksi yanlarını bildiğimiz halde implemente etmekten kaçamadığımız veya implemente…

2 yıl ago

.NET Microservice’lerinde Outbox Pattern’ı ile Eventual Consistency için Atomicity Sağlama

{:tr}Bildiğimiz gibi microservice architecture'ına adapte olmanın bir çok artı noktası olduğu gibi, maalesef getirdiği bazı…

2 yıl ago

Dapr ve .NET Kullanarak Minimum Efor ile Microservice’ler Geliştirmek – 02 (Azure Container Apps)

{:tr}Bir önceki makale serisinde Dapr projesinden ve faydalarından bahsedip, local ortamda self-hosted mode olarak .NET…

2 yıl ago