Güzel bir konu ile tekrar merhaba arkadaşlar.
Bu makalemde sizlere nesnenin hallerini tutma ihtiyacı duyduğunuzda yani nesnenin farklı halleri arasında geçiş yapabilmeniz gerektiği durumlarda kullanabileceğiniz güzel bir tasarım deseni olan Memento Pattern’inin kullanımından bahsedeceğim.

Açıkcası GOF tasarım desenleri hakkındaki makalelerime başlangıcımı uzun zamandır düşünüyorum fakat bir türlü fırsat bulamamıştım, bir projem üzerinde kullanmam gerekince bu bana adı üstünde Hatırlayıcı(Memento) bana başlamamı hatırlattı. 🙂

Kendisi Behavioral tasarım kalıpları gurubunda olan bir tasarım desenidir. Yukarıda da bahsettiğimiz üzere nesnenin bazı özelliklerinin veya tamamını tutabilmemizi sağlamaktadır.

Hızlıca UML Diagramına bakmak gerekirse:

Originator: Bu sınıf durumu tutulacak olan nesnemiz oluyor, eski veya yeni halini tutmamızı sağlayacak metotlar burada yer alacak.
Memento: Bu sınıf ise, asıl nesnemizin istediğimiz alanları tutan sınıftır.
Caretaker: Geri dönüş adımlarımızı Memento tipinden tutacak olan sınıftır.

UML diagramını incelediğimize göre pekiştirmek için hemen basit bir örnek yapalım.

Web veya Windows tabanlı bir uygulama geliştirdiğimizi düşünelim. Uygulamamızda kullanıcının kendi ayarlarını yapabileceği bir Settings bölümü bulunsun. Memento desenini uygulayacağımız nokta ise: Get Default Settings tarzında bir buton koyacağız ve kullanıcı değiştirdiği ayarı orjinal haline geri döndürebilmesini sağlıyor olacağız.

Öncelikle Settings sınıfımızı oluşturalım ve bu bizim Originator‘umuzu temsil edecek yani ayarların tutulacağı sınıfımız.

    /// <summary>
    /// Originator - Ayarlarımızın tutulduğu sınıfımız. 
    /// </summary>
    public class Settings
    {
        // Kullanıcının güncelleyebileceği ayarlar propertyleri.
        public string UserName { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
        public bool RememberMe { get; set; }

        // Çağırıldığında Settings nesnemizin kopyasını oluşturacak olan metotumuz.
        public SettingsMemento Backup()
        {
            SettingsMemento settingsMemento = new SettingsMemento
            {
                UserName = this.UserName,
                Password = this.Password,
                Email = this.Email,
                RememberMe = this.RememberMe
            };
            return settingsMemento;
        }

        // Çağırıldığında daha önceden kopyasını aldığımız Memento sınıfındaki bilgileri Settings nesnemize geri atıyoruz.
        public void GetDefaultSettings(SettingsMemento settingsMemento)
        {
            this.UserName = settingsMemento.UserName;
            this.Password = settingsMemento.Password;
            this.Email = settingsMemento.Email;
            this.RememberMe = settingsMemento.RememberMe;
        }

        public override string ToString()
        {
            return string.Format("UserName: {0} Password: {1} Email: {2} RememberMe: {3}", this.UserName, this.Password, this.Email, this.RememberMe.ToString());
        }
    }

Settings sınıfımızı oluşturduğumuza göre şimdi Memento‘yu üstlenecek olan SettingsMemento sınıfımızı hazırlayalım.

    /// <summary>
    /// Memento - Asıl nesnemizin alanlarını tutan memento sınıfımız.
    /// </summary>
    public class SettingsMemento
    {
        public string UserName { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
        public bool RememberMe { get; set; }
    }

Şimdi SettingsCareTaker sınıfımızı oluşturarak geri dönüş adımlarımızı Memento tipinden tutacak olan sınıfımızı hazırlayalım.

    /// <summary>
    /// Caretaker - Geri dönüş adımlarımız burada tutulacak.
    /// </summary>
    public class SettingsCaretaker
    {
        public SettingsMemento Memento { get; set; }
    }

Ever her şey hazır olduğuna göre şimdi kullanımına bakalım.

            SettingsCaretaker settingsCaretaker = new SettingsCaretaker();

            Settings settings = new Settings();
            settings.UserName = "GokGokalp";
            settings.Password = "123456";
            settings.Email = "gok.gokalp@yahoo.com";
            settings.RememberMe = true;

            Console.WriteLine(settings.ToString() + Environment.NewLine);

            // Kopyasını alıyoruz.
            settingsCaretaker.Memento = settings.Backup();

            settings.Password = "654321";
            settings.RememberMe = false;

            Console.WriteLine(settings.ToString() + Environment.NewLine);

            // Caretaker üzerinde bulunan kopyasından orjinaline geri döndürüyoruz nesnemizi.
            settings.GetDefaultSettings(settingsCaretaker.Memento);

            Console.WriteLine(settings.ToString());
            Console.ReadLine();

İşte bu kadar basit. Umarım anlaşılması kolay bir örnek olmuştur.

Diğer makalelerimde görüşmek dileğiyle.

 

Gökhan Gökalp

Recent Posts

Securing the Supply Chain of Containerized Applications to Reduce Security Risks (Policy Enforcement-Automated Governance with OPA Gatekeeper and Ratify) – Part 2

{:tr} Makalenin ilk bölümünde, Software Supply Chain güvenliğinin öneminden ve containerized uygulamaların güvenlik risklerini azaltabilmek…

5 months ago

Securing the Supply Chain of Containerized Applications to Reduce Security Risks (Security Scanning, SBOMs, Signing&Verifying Artifacts) – Part 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 months ago

Delegating Identity & Access Management to Azure AD B2C and Integrating with .NET

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

12 months ago

How to Order Events in Microservices by Using Azure Service Bus (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 years ago

Providing Atomicity for Eventual Consistency with Outbox Pattern in .NET Microservices

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

2 years ago

Building Microservices by Using Dapr and .NET with Minimum Effort – 02 (Azure Container Apps)

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

2 years ago