Memento Design Pattern Nedir?

Fatih İzgi
Kodcular
Published in
3 min readApr 7, 2024

--

Design Patterns eğitim serisindeki ilk yazımızda, tasarım desenlerinin “Yazılımcıların sıklıkla karşılaştığı problemlere ve yazılımların doğasında bulunan genel ihtiyaçlara getirilen çözümler” olduğunu söylemiştik. Sık karşılaşılan problemlerden bir tanesi ise; nesnenin mevcut yapısını değiştirmeden, nesne durumlarını saklama ihtiyacıdır. Bu yazımızda, bu problemi çözmek için kullanabileceğimiz Memento Design Pattern yapısını inceleyeceğiz.

Konuya başlamadan önce problemin ne olduğunu biraz analiz edelim :

Satranç uygulamaları, oyunlardaki tüm hamleleri hafızalarında tutar. Böylece oyunculardan herhangi biri hamlesini geri alabilme imkanına sahiptir ve bu oyunun gidişatını etkiler. Oyunda “geri al” seçeneğinin kapalı olduğu durumlarda(yani hamleleri hafızasında tutmasının oyun gidişatına hiçbir etkisinin olmadığı durumlarda bile) ise kullanıcılara, oyun bittikten sonra herhangi bir noktaya geri dönerek analiz yapabilme imkanı sunar. Yukarıda bahsedilen “nesnenin mevcut yapısını değiştirmeden nesne durumlarını saklama” durumu tam olarak budur. Nihayetinde oyun artık geçmişte kalmıştır ve sonuç değişmeyecektir fakat oyundaki tüm hamleleri ayrı ayrı inceleme imkanımız vardır. Bu durumun en güzel örneklerinden bir diğeri ise sıklıkla kullanıdığımız versiyon kontrol sistemleridir. Atılan tüm commit’lerin saklanması ana projeye hiçbir etki vermeyecek ve proje mevcut halindeki gibi çalışacaktır ancak her zaman projeyi geçmişteki bir versiyonuna geri çevirme veya tüm adımlarını inceleyebilme imkanına sahibizdir.

Bir not tutma uygulaması geliştirdiğimizi düşünelim. Uygulama, kullanıcılara “geri alma” imkanı veriyor olsun. Bunların dışında yazılan ilk yazıyı görüntüleme ve yazıda kaç kez güncelleme yapıldığını da görebiliyor olalım. Bunun için uygulamanın, yazılan her şeyi hafızasında tutması gerekecektir. Elbette bu sorumluluk Text nesnesine ait olmamalıdır çünkü bu tasarım Single Responsibility prensibine aykırı olacaktır. Bu sebeple, bu işi yapacak bir başka sınıf(Memento) olmalıdır ve Text nesnesi bu nesneye sahip olmalıdır.

Memento Design Pattern, bir nesnenin durumlarını (nesnenin güncel durumuna etki vermeden) saklamak amacı ile kullanılır. Memento, “hatıra, yadigar” anlamlarına gelir. Davranışsal(Behavioral) tasarım desenlerinden biridir ve kullanılması ile birlikte hata giderme, analiz edebilme, geçmişe dönebilme gibi faydalar sağlar.

Öncelikle problemimizi yazılıma aktarmak adına örnek bir yapı oluşturalım :

Öncelikle Text isimli bir sınıf oluşturduk. Bu sınıf, ekrandaki yazımızı tutmak için String tipinde “text” değişkenine ve yapılan işlemleri hafızasında tutmaktan sorumlu olan TextMemento tipinde “memento” nesnesine sahip. Sınıf içerisinde bulunan add() ve undo() metotlarında, yapılan her işlem ile ilgili memento nesnesi de haberdar edilir. Bu sayede memento nesnesi, yeni bir ekleme yapıldığını veya geri alma işlemi yapıldığını bilecektir. Ekleme ve geri alma işlemleri ile birlikte, memento nesnesinin haberdar edilmesi de Text sınıfının sorumluluğundadır.

TextMemento sınıfını inceleyecek olursak :

Görüldüğü üzere, TextMemento sınıfı bir adet textList değişkenine sahiptir. Her add() ve undo() işlemi sonucu oluşan yazı, listeye yeni eleman olarak eklenir. Böylece, yazıların tüm versiyonlarına geri dönmek mümkün hale gelir. Ayrıca sınıf, yazılan ilk texti tutabilmek adına firstText değişkenine ve kaç adet add()/undo() işlemi yapıldığını tutmak adına updateCounter değişkenine sahiptir. Bu işlemlerin takibini Text sınıfına bırakmayarak bir nevi ona yardımcı olur ve SRP’nin korunmasını sağlar.

Yazı yazıp üzerinde işlemler gerçekleştirmek istersek :

Output :

Text : Daha fazla konuşabilmek isterdim ama yemeğe eski bir arkadaşım davetli.

Text :

Text : Kuzuların çığlıkları dindiğinde bana haber verirsin değil mi?

İlk Text : Daha fazla konuşabilmek isterdim

Güncelleme Sayısı : 4

Sonuç olarak ekranda yazılan yazılara kaydetme ve geri alma seçenekleri ile birlikte yazılan ilk yazıyı tutma, yazının kaç kez güncellendiğini takip edebilme gibi işlemleri gerçekleştirdik. Bunu yaparken Text sınıfına yalnızca yazma/geri alma sorumluluğunu yükledik ve detaylar için ona yardımcı olacak olan TextMemento sınıfını kullandık. Böylece SRP’ye uygun bir tasarım ortaya koyabildik.

NOT 1 : Kaydet, geri al, sil vb. işlemler için Memento ve Command kalıpları birlikte kullanılabilir.

NOT 2 : Hafızalama işlemi Liste vb. bir yapı üzerinden gerçekleştirilirken Memento’yu Iterator kalıbı ile birlikte kullanmak mümkündür.

NOT 3 : Hafızada tutulması gereken işlem sayısı arttıkça Memento’yu uygulamanın maliyeti artacaktır.

TÜM YAPI :

Memento Design Pattern konusunun ayrıntılarını ve inceliklerini öğrendiğimize göre tüm yapıyı incelemeye başlayabiliriz :

Output :

Text : Daha fazla konuşabilmek isterdim ama yemeğe eski bir arkadaşım davetli.

Text :

Text : Kuzuların çığlıkları dindiğinde bana haber verirsin değil mi?

İlk Text : Daha fazla konuşabilmek isterdim

Güncelleme Sayısı : 4

Yararlandığım Kaynaklar :

1- GeeksForGeeks

2- Refactoring.Guru

3- Baeldung

--

--