[{"data":1,"prerenderedAt":2317},["ShallowReactive",2],{"post-\u002Ftr\u002Fmemento-tasarim-deseni-nedir":3},{"page":4,"translation":2161,"nav":2175,"related":2295,"random":2306},{"id":5,"title":6,"body":7,"categories":2159,"category":2161,"date":2162,"description":2163,"draft":2164,"extension":2165,"image":2166,"kind":2161,"lang":177,"meta":2167,"navigation":330,"path":2120,"readingTime":375,"seo":2168,"slug":2169,"stem":2170,"tags":2171,"translationKey":2161,"type":2160,"updated":2161,"__hash__":2174},"postsTr\u002Ftr\u002Fmemento-tasarim-deseni-nedir.md","Memento Tasarım Deseni Nedir?",{"type":8,"value":9,"toc":2145},"minimark",[10,48,57,70,73,76,81,92,94,98,101,104,111,117,120,123,126,128,132,135,140,147,153,158,165,170,240,242,246,251,254,259,262,264,268,298,300,304,308,1376,1380,2029,2031,2035,2040,2062,2067,2097,2102,2141],[11,12,13,21],"blockquote",{},[14,15,16,17],"p",{},"💡 ",[18,19,20],"strong",{},"Özet (TL;DR):",[22,23,24,31,37],"ul",{},[25,26,27,30],"li",{},[18,28,29],{},"Amacı:"," Bir nesnenin iç detaylarını ve kapsam sınırlarını (encapsulation) ihlal etmeden, önceki durumunun (state) anlık görüntüsünü (snapshot) kaydetmeyi ve geri yüklemeyi sağlayan davranışsal (behavioral) bir tasarım desenidir.",[25,32,33,36],{},[18,34,35],{},"Çözdüğü Sorun:"," \"Geri Al\" (Undo\u002FRedo) işlemlerinde nesnelerin özel (private) alanlarına doğrudan erişim gereksinimini ortadan kaldırır ve kodun bağımlılık (coupling) seviyesini düşürür.",[25,38,39,42,43,47],{},[18,40,41],{},"Yöntem:"," Nesne kendi durumunu temsil eden özel bir ",[44,45,46],"code",{},"Memento"," nesnesi üretir. Bu nesne sadece asıl sınıf (Originator) tarafından okunabilirken, depolayıcı (Caretaker) tarafından içeriği görülmeden saklanır.",[14,49,50,51,56],{},"Bu yazı ",[52,53,55],"a",{"href":54},"\u002Ftr\u002Fdesign-patterns-tasarim-desenleri-nedir","Design Patterns\u002FTasarım Desenleri nedir?"," başlıklı yazı dizisinin bir parçasıdır.",[14,58,59,60,69],{},"Bu içerik ağırlıklı olarak ",[52,61,68],{"href":62,"rel":63,"target":67},"https:\u002F\u002Frefactoring.guru\u002Fdesign-patterns",[64,65,66],"nofollow","noopener","noreferrer","_blank","refactoring.guru"," sitesindeki içeriğin tercümesi ve derlenmesinden oluşturulmuştur.",[14,71,72],{},"Tüm tasarım desenleri ya da diğer adıyla tasarım kalıplarına yönelik ayrıntılı içeriklere yazının sonundaki bağlantılardan ulaşabilirsiniz.",[74,75],"hr",{},[77,78,80],"h2",{"id":79},"memento-tasarım-deseninin-amacı","Memento Tasarım Deseninin Amacı",[14,82,83,85,86,88,89,91],{},[18,84,46],{}," adını duyunca sizin de aklınıza Christopher Nolan'ın yönetmenliğini yaptığı o meşhur film mi geliyor bilmiyorum ama bu yazıda tasarım deseni (design pattern) olan ",[18,87,46],{},"'yu inceleyeceğiz. ",[18,90,46],{},", bir nesnenin önceki durumunu, uygulama detaylarını açığa çıkarmadan kaydetmeniz ve geri getirmenizi sağlayan bir tasarım desenidir.",[74,93],{},[77,95,97],{"id":96},"sorun","Sorun",[14,99,100],{},"Bir metin editörü uygulaması yazdığınızı düşünün. Uygulamanız sadece metni düzenleme işlemleri değil, metin biçimlendirme, metin içine görseller ekleme gibi özelliklere de sahip olsun.",[14,102,103],{},"Diyelim ki kullanıcıların yaptıkları değişiklikleri geri alabilmelerini sağlamaya karar verdiniz. Bu özellik yıllardır çoğu uygulamada varsayılan olarak bulunduğu için kullanıcıların uygulamanızdan böyle bir beklentisi var. Bunu şu şekilde doğrudan uygulamaya karar verdiniz: Her işlemden önce uygulama tüm nesnelerin mevcut durumlarını bir depolama alanına kaydedecek, kullanıcı geri dönmeye karar verirse uygulamanız saklama alanından en son anı alıp bunu bütün nesneleri o hale döndürmek için kullanacak.",[14,105,106],{},[107,108],"img",{"alt":109,"src":110},"Memento deseni nedir","\u002Fimages\u002Fmemento-tasarim-deseni-nedir\u002Fneden-memento-tasarim-deseni.avif",[14,112,113],{},[114,115,116],"em",{},"Nesnenin özel (private) alanlarını nasıl kopyalayacaksınız?",[14,118,119],{},"Dahası da var. Editörün anlık görüntülerini ele alalım. Bu görüntülerin içinde ne olur? En azından mevcut metin, imlecin o andaki konumu, kaydırma çubuğunun konumu vb. bilgiler olmalı değil mi? Bir anlık görüntü oluşturmak için bütün bu değerleri toplamalı ve bir çeşit konteyner içine yerleştirmelisiniz.",[14,121,122],{},"Bu konteyner listelerini de büyük ihtimalle geçmişi gösteren bir liste içinde tutacaksınız. Sonuç olarak bu konteynerler bir sınıfa ait nesneler haline gelecekler. Bu sınıfın neredeyse hiçbir metodu yokken, editörün durumunu yansıtan bir sürü alanı olacak. Diğer nesnelerin bu görüntüye yazmaları veya okuyabilmeleri için bu alanları açık (public) yapmanız gerekecek. Bu da özel (private) olsun ya da olmasın editörün durumundaki tüm bilgiyi açık hale getirecek. Diğer sınıflar, anlık görüntü sınıfındaki en ufak değişiklikten bile etkilenebilecek ve bağımlı hale gelecekler (normalde özel alanlar ve metotların kendi iç dinamikleriyle hallolacak konularda bile).",[14,124,125],{},"Görünüşe göre bir çıkmaza girdik: Ya ilgili sınıfların tüm detaylarını dışa açık (public) hale getirecek ve çok kırılgan bir yapıya dönüştüreceksiniz ya da durumlarına erişimi kısıtlayacak ama o zaman da anlık görüntü oluşturamayacaksınız. \"Geri al\" özelliğini uygulamak için başka bir yol yok mu?",[74,127],{},[77,129,131],{"id":130},"çözüm","Çözüm",[14,133,134],{},"Az önce yaşadığımız tüm sorunlar kapsamı sınırlandırmanın (encapsulation) bozulmasından kaynaklanıyor. Bazı nesneler yapmaları gerekenden daha fazlasını yapıyorlar. Bir işlemi ilgili nesneye yaptırmak yerine, o işlemi yapmak için gereken veriyi nesnenin özel (private) alanlarına müdahale ederek almaya çalışıyorlar.",[14,136,137,139],{},[18,138,46],{}," deseni anlık görüntü oluşturma işini, asıl nesnenin kendisine delege eder. Başka nesnelerin dışarıdan editörün durumunu kopyalamaya çalışması yerine editör sınıfının kendi anlık görüntüsünü oluşturmasını sağlar.",[14,141,142,143,146],{},"Bu desen nesnenin durum kopyasını ",[18,144,145],{},"memento"," adı verilen özel bir nesnede saklamayı önerir. Memento'nun içeriği, kendisini oluşturandan başka hiçbir nesne tarafından erişilebilir değildir. Diğer nesneler, Memento ile sınırlı bir arayüz üzerinden iletişim kurarak sadece anlık görüntü meta bilgilerine (oluşturma zamanı, yapılan işlemin adı vb. gibi bilgiler) ulaşabilirler. Nesnenin orijinal durumu ise görüntünün kendisinde yer alır.",[14,148,149],{},[107,150],{"alt":151,"src":152},"Memento deseni örneği","\u002Fimages\u002Fmemento-tasarim-deseni-nedir\u002Fmemento-deseni-ornek.avif",[14,154,155],{},[114,156,157],{},"Orijinal nesne mementoya tam erişime sahipken, bakıcılar sadece sınırlı bilgilere ulaşabilirler.",[14,159,160,161,164],{},"Bu sınırlayıcı politika mementoları, ",[18,162,163],{},"bakıcı (caretaker)"," olarak adlandırılan başka nesnelerin içinde depolamaya olanak verir. Bakıcı memento ile çok sınırlı bir arayüz üzerinden iletişim kurduğu için memento içinde saklanan görüntüye erişemez. Aynı zamanda asıl nesnenin memento içerisindeki tüm nesnelere erişebilmesi ve gerektiğinde önceki duruma getirebilmesi gerekir.",[166,167,169],"h3",{"id":168},"memento-ve-prototype-desenleri-arasındaki-fark","Memento ve Prototype Desenleri Arasındaki Fark",[171,172,173,190],"table",{},[174,175,176],"thead",{},[177,178,179,184,187],"tr",{},[180,181,183],"th",{"align":182},"left","Özellik",[180,185,186],{"align":182},"Memento Deseni",[180,188,189],{"align":182},"Prototype Deseni",[191,192,193,207,220],"tbody",{},[177,194,195,201,204],{},[196,197,198],"td",{"align":182},[18,199,200],{},"Temel Amaç",[196,202,203],{"align":182},"Bir nesnenin geçmişteki belirli bir durumuna geri dönebilmek (Undo\u002FRedo).",[196,205,206],{"align":182},"Mevcut bir nesnenin kopyasını oluşturarak yeni nesneler üretmek.",[177,208,209,214,217],{},[196,210,211],{"align":182},[18,212,213],{},"Kapsülleme (Encapsulation)",[196,215,216],{"align":182},"Özel (private) alanları korur; durumu saklayan sınıf dışında kimse verilere erişemez.",[196,218,219],{"align":182},"Klonlanan nesnenin tüm açık alanlarını kopyalar, kapsülleme sınırlarını esnetebilir.",[177,221,222,227,233],{},[196,223,224],{"align":182},[18,225,226],{},"Kullanım Yöntemi",[196,228,229,230,232],{"align":182},"Durum ",[44,231,46],{}," adında ayrı bir ara nesnede saklanır.",[196,234,235,236,239],{"align":182},"Nesnenin kendisi klonlanır (",[44,237,238],{},"clone()"," metoduyla).",[74,241],{},[77,243,245],{"id":244},"uygulanabilirlik","Uygulanabilirlik",[14,247,248],{},[18,249,250],{},"Bir nesneyi önceki duruma getirmeniz için anlık görüntüler oluşturmanız gerekiyorsa Memento desenini kullanabilirsiniz.",[14,252,253],{},"Memento deseni bir nesnenin özel alanlar da dahil olmak üzere tam bir kopyasını oluşturmanıza ve nesneden ayrı olarak saklamanıza olanak veren bir desendir. Çoğu insan bu deseni \"geri al\" kullanımı nedeniyle biliyor olsa da işleme (transaction) dayalı işlemlerle uğraşırken de vazgeçilmez olanaklar sağlar (hata durumunda işlemi geri almak için).",[14,255,256],{},[18,257,258],{},"Bir nesnenin alanlarına, getirici (getter) ve ayarlayıcılarına (setter) doğrudan ulaşmak nesnenin kapsam sınırlarını ihlal ediyorsa bu deseni kullanabilirsiniz.",[14,260,261],{},"Memento, bir nesnenin durumunu saklamak için sorumluluğu nesnenin kendisine verir. Başka hiçbir nesne durumun bu anlık görüntüsüne ulaşamaz, böylece nesnenin verileri güvenli ve emniyetli kalır.",[74,263],{},[77,265,267],{"id":266},"diğer-tasarım-desenleri-ile-i̇lişkisi","Diğer Tasarım Desenleri ile İlişkisi",[22,269,270,280,289],{},[25,271,272,273,276,277,279],{},"Geri Al (Undo) işlevi için ",[18,274,275],{},"Command"," ve ",[18,278,46],{},"'yu birlikte uygulayabilirsiniz. Bu durumda Command'ler hedef nesneye bazı işlemler yapmaktan sorumlu iken, Memento'lar Command çalıştırılmadan önce nesnenin durumunu kaydetmek için kullanılır.",[25,281,282,283,276,286,288],{},"Mevcut dolaşım durumunu yakalamak ve gerekirse geri döndürmek için ",[18,284,285],{},"Iterator",[18,287,46],{},"'yu birlikte kullanabilirsiniz.",[25,290,291,294,295,297],{},[18,292,293],{},"Prototype"," bazen ",[18,296,46],{},"'ya basit bir alternatif olabilir. Bu durum, saklamak istediğiniz nesne basit, dış kaynaklarla bağlantısı olmayan veya bu kaynaklara yeniden bağlanması kolay bir nesne ise geçerlidir.",[74,299],{},[77,301,303],{"id":302},"memento-tasarım-deseni-kod-örnekleri","Memento Tasarım Deseni Kod Örnekleri",[166,305,307],{"id":306},"örnek-php-kodu","Örnek PHP Kodu",[309,310,315],"pre",{"className":311,"code":312,"language":313,"meta":314,"style":314},"language-php shiki shiki-themes github-light github-dark","\u003C?php\n\nnamespace RefactoringGuru\\Memento\\Conceptual;\n\n\u002F**\n * The Originator holds some important state that may change over time. It also\n * defines a method for saving the state inside a memento and another method for\n * restoring the state from it.\n *\u002F\nclass Originator\n{\n    \u002F**\n     * @var string For the sake of simplicity, the originator's state is stored\n     * inside a single variable.\n     *\u002F\n    private $state;\n\n    public function __construct(string $state)\n    {\n        $this->state = $state;\n        echo \"Originator: My initial state is: {$this->state}\\n\";\n    }\n\n    \u002F**\n     * The Originator's business logic may affect its internal state. Therefore,\n     * the client should backup the state before launching methods of the\n     * business logic via the save() method.\n     *\u002F\n    public function doSomething(): void\n    {\n        echo \"Originator: I'm doing something important.\\n\";\n        $this->state = $this->generateRandomString(30);\n        echo \"Originator: and my state has changed to: {$this->state}\\n\";\n    }\n\n    private function generateRandomString(int $length = 10): string\n    {\n        return substr(\n            str_shuffle(\n                str_repeat(\n                    $x = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',\n                    ceil($length \u002F strlen($x))\n                )\n            ),\n            1,\n            $length,\n        );\n    }\n\n    \u002F**\n     * Saves the current state inside a memento.\n     *\u002F\n    public function save(): Memento\n    {\n        return new ConcreteMemento($this->state);\n    }\n\n    \u002F**\n     * Restores the Originator's state from a memento object.\n     *\u002F\n    public function restore(Memento $memento): void\n    {\n        $this->state = $memento->getState();\n        echo \"Originator: My state has changed to: {$this->state}\\n\";\n    }\n}\n\n\u002F**\n * The Memento interface provides a way to retrieve the memento's metadata, such\n * as creation date or name. However, it doesn't expose the Originator's state.\n *\u002F\ninterface Memento\n{\n    public function getName(): string;\n\n    public function getDate(): string;\n}\n\n\u002F**\n * The Concrete Memento contains the infrastructure for storing the Originator's\n * state.\n *\u002F\nclass ConcreteMemento implements Memento\n{\n    private $state;\n\n    private $date;\n\n    public function __construct(string $state)\n    {\n        $this->state = $state;\n        $this->date = date('Y-m-d H:i:s');\n    }\n\n    \u002F**\n     * The Originator uses this method when restoring its state.\n     *\u002F\n    public function getState(): string\n    {\n        return $this->state;\n    }\n\n    \u002F**\n     * The rest of the methods are used by the Caretaker to display metadata.\n     *\u002F\n    public function getName(): string\n    {\n        return $this->date . \" \u002F (\" . substr($this->state, 0, 9) . \"...)\";\n    }\n\n    public function getDate(): string\n    {\n        return $this->date;\n    }\n}\n\n\u002F**\n * The Caretaker doesn't depend on the Concrete Memento class. Therefore, it\n * doesn't have access to the originator's state, stored inside the memento. It\n * works with all mementos via the base Memento interface.\n *\u002F\nclass Caretaker\n{\n    \u002F**\n     * @var Memento[]\n     *\u002F\n    private $mementos = [];\n\n    \u002F**\n     * @var Originator\n     *\u002F\n    private $originator;\n\n    public function __construct(Originator $originator)\n    {\n        $this->originator = $originator;\n    }\n\n    public function backup(): void\n    {\n        echo \"\\nCaretaker: Saving Originator's state...\\n\";\n        $this->mementos[] = $this->originator->save();\n    }\n\n    public function undo(): void\n    {\n        if (!count($this->mementos)) {\n            return;\n        }\n        $memento = array_pop($this->mementos);\n\n        echo \"Caretaker: Restoring state to: \" . $memento->getName() . \"\\n\";\n        try {\n            $this->originator->restore($memento);\n        } catch (\\Exception $e) {\n            $this->undo();\n        }\n    }\n\n    public function showHistory(): void\n    {\n        echo \"Caretaker: Here's the list of mementos:\\n\";\n        foreach ($this->mementos as $memento) {\n            echo $memento->getName() . \"\\n\";\n        }\n    }\n}\n\n\u002F**\n * Client code.\n *\u002F\n$originator = new Originator(\"Super-duper-super-puper-super.\");\n$caretaker = new Caretaker($originator);\n\n$caretaker->backup();\n$originator->doSomething();\n\n$caretaker->backup();\n$originator->doSomething();\n\n$caretaker->backup();\n$originator->doSomething();\n\necho \"\\n\";\n$caretaker->showHistory();\n\necho \"\\nClient: Now, let's rollback!\\n\\n\";\n$caretaker->undo();\n\necho \"\\nClient: Once more!\\n\\n\";\n$caretaker->undo();\n","php","",[44,316,317,325,332,338,343,349,355,361,367,373,379,385,391,397,403,409,415,420,426,432,438,444,450,455,460,466,472,478,483,489,494,500,506,512,517,522,528,533,539,545,551,557,563,569,575,581,587,593,598,603,608,614,619,625,630,636,641,646,651,657,662,668,673,679,685,690,696,701,706,712,718,723,729,734,740,745,751,756,761,766,772,778,783,789,794,799,804,810,815,820,825,830,836,841,846,851,857,862,868,873,879,884,889,894,900,905,911,916,922,927,932,938,943,949,954,959,964,969,975,981,987,992,998,1003,1008,1014,1019,1025,1030,1035,1041,1046,1052,1057,1063,1068,1074,1079,1084,1090,1095,1101,1107,1112,1117,1123,1128,1134,1140,1146,1152,1157,1163,1169,1175,1181,1187,1192,1197,1202,1208,1213,1219,1225,1231,1236,1241,1246,1251,1256,1262,1267,1273,1279,1284,1290,1296,1301,1306,1311,1316,1321,1326,1331,1337,1343,1348,1354,1360,1365,1371],{"__ignoreMap":314},[318,319,322],"span",{"class":320,"line":321},"line",1,[318,323,324],{},"\u003C?php\n",[318,326,328],{"class":320,"line":327},2,[318,329,331],{"emptyLinePlaceholder":330},true,"\n",[318,333,335],{"class":320,"line":334},3,[318,336,337],{},"namespace RefactoringGuru\\Memento\\Conceptual;\n",[318,339,341],{"class":320,"line":340},4,[318,342,331],{"emptyLinePlaceholder":330},[318,344,346],{"class":320,"line":345},5,[318,347,348],{},"\u002F**\n",[318,350,352],{"class":320,"line":351},6,[318,353,354],{}," * The Originator holds some important state that may change over time. It also\n",[318,356,358],{"class":320,"line":357},7,[318,359,360],{}," * defines a method for saving the state inside a memento and another method for\n",[318,362,364],{"class":320,"line":363},8,[318,365,366],{}," * restoring the state from it.\n",[318,368,370],{"class":320,"line":369},9,[318,371,372],{}," *\u002F\n",[318,374,376],{"class":320,"line":375},10,[318,377,378],{},"class Originator\n",[318,380,382],{"class":320,"line":381},11,[318,383,384],{},"{\n",[318,386,388],{"class":320,"line":387},12,[318,389,390],{},"    \u002F**\n",[318,392,394],{"class":320,"line":393},13,[318,395,396],{},"     * @var string For the sake of simplicity, the originator's state is stored\n",[318,398,400],{"class":320,"line":399},14,[318,401,402],{},"     * inside a single variable.\n",[318,404,406],{"class":320,"line":405},15,[318,407,408],{},"     *\u002F\n",[318,410,412],{"class":320,"line":411},16,[318,413,414],{},"    private $state;\n",[318,416,418],{"class":320,"line":417},17,[318,419,331],{"emptyLinePlaceholder":330},[318,421,423],{"class":320,"line":422},18,[318,424,425],{},"    public function __construct(string $state)\n",[318,427,429],{"class":320,"line":428},19,[318,430,431],{},"    {\n",[318,433,435],{"class":320,"line":434},20,[318,436,437],{},"        $this->state = $state;\n",[318,439,441],{"class":320,"line":440},21,[318,442,443],{},"        echo \"Originator: My initial state is: {$this->state}\\n\";\n",[318,445,447],{"class":320,"line":446},22,[318,448,449],{},"    }\n",[318,451,453],{"class":320,"line":452},23,[318,454,331],{"emptyLinePlaceholder":330},[318,456,458],{"class":320,"line":457},24,[318,459,390],{},[318,461,463],{"class":320,"line":462},25,[318,464,465],{},"     * The Originator's business logic may affect its internal state. Therefore,\n",[318,467,469],{"class":320,"line":468},26,[318,470,471],{},"     * the client should backup the state before launching methods of the\n",[318,473,475],{"class":320,"line":474},27,[318,476,477],{},"     * business logic via the save() method.\n",[318,479,481],{"class":320,"line":480},28,[318,482,408],{},[318,484,486],{"class":320,"line":485},29,[318,487,488],{},"    public function doSomething(): void\n",[318,490,492],{"class":320,"line":491},30,[318,493,431],{},[318,495,497],{"class":320,"line":496},31,[318,498,499],{},"        echo \"Originator: I'm doing something important.\\n\";\n",[318,501,503],{"class":320,"line":502},32,[318,504,505],{},"        $this->state = $this->generateRandomString(30);\n",[318,507,509],{"class":320,"line":508},33,[318,510,511],{},"        echo \"Originator: and my state has changed to: {$this->state}\\n\";\n",[318,513,515],{"class":320,"line":514},34,[318,516,449],{},[318,518,520],{"class":320,"line":519},35,[318,521,331],{"emptyLinePlaceholder":330},[318,523,525],{"class":320,"line":524},36,[318,526,527],{},"    private function generateRandomString(int $length = 10): string\n",[318,529,531],{"class":320,"line":530},37,[318,532,431],{},[318,534,536],{"class":320,"line":535},38,[318,537,538],{},"        return substr(\n",[318,540,542],{"class":320,"line":541},39,[318,543,544],{},"            str_shuffle(\n",[318,546,548],{"class":320,"line":547},40,[318,549,550],{},"                str_repeat(\n",[318,552,554],{"class":320,"line":553},41,[318,555,556],{},"                    $x = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',\n",[318,558,560],{"class":320,"line":559},42,[318,561,562],{},"                    ceil($length \u002F strlen($x))\n",[318,564,566],{"class":320,"line":565},43,[318,567,568],{},"                )\n",[318,570,572],{"class":320,"line":571},44,[318,573,574],{},"            ),\n",[318,576,578],{"class":320,"line":577},45,[318,579,580],{},"            1,\n",[318,582,584],{"class":320,"line":583},46,[318,585,586],{},"            $length,\n",[318,588,590],{"class":320,"line":589},47,[318,591,592],{},"        );\n",[318,594,596],{"class":320,"line":595},48,[318,597,449],{},[318,599,601],{"class":320,"line":600},49,[318,602,331],{"emptyLinePlaceholder":330},[318,604,606],{"class":320,"line":605},50,[318,607,390],{},[318,609,611],{"class":320,"line":610},51,[318,612,613],{},"     * Saves the current state inside a memento.\n",[318,615,617],{"class":320,"line":616},52,[318,618,408],{},[318,620,622],{"class":320,"line":621},53,[318,623,624],{},"    public function save(): Memento\n",[318,626,628],{"class":320,"line":627},54,[318,629,431],{},[318,631,633],{"class":320,"line":632},55,[318,634,635],{},"        return new ConcreteMemento($this->state);\n",[318,637,639],{"class":320,"line":638},56,[318,640,449],{},[318,642,644],{"class":320,"line":643},57,[318,645,331],{"emptyLinePlaceholder":330},[318,647,649],{"class":320,"line":648},58,[318,650,390],{},[318,652,654],{"class":320,"line":653},59,[318,655,656],{},"     * Restores the Originator's state from a memento object.\n",[318,658,660],{"class":320,"line":659},60,[318,661,408],{},[318,663,665],{"class":320,"line":664},61,[318,666,667],{},"    public function restore(Memento $memento): void\n",[318,669,671],{"class":320,"line":670},62,[318,672,431],{},[318,674,676],{"class":320,"line":675},63,[318,677,678],{},"        $this->state = $memento->getState();\n",[318,680,682],{"class":320,"line":681},64,[318,683,684],{},"        echo \"Originator: My state has changed to: {$this->state}\\n\";\n",[318,686,688],{"class":320,"line":687},65,[318,689,449],{},[318,691,693],{"class":320,"line":692},66,[318,694,695],{},"}\n",[318,697,699],{"class":320,"line":698},67,[318,700,331],{"emptyLinePlaceholder":330},[318,702,704],{"class":320,"line":703},68,[318,705,348],{},[318,707,709],{"class":320,"line":708},69,[318,710,711],{}," * The Memento interface provides a way to retrieve the memento's metadata, such\n",[318,713,715],{"class":320,"line":714},70,[318,716,717],{}," * as creation date or name. However, it doesn't expose the Originator's state.\n",[318,719,721],{"class":320,"line":720},71,[318,722,372],{},[318,724,726],{"class":320,"line":725},72,[318,727,728],{},"interface Memento\n",[318,730,732],{"class":320,"line":731},73,[318,733,384],{},[318,735,737],{"class":320,"line":736},74,[318,738,739],{},"    public function getName(): string;\n",[318,741,743],{"class":320,"line":742},75,[318,744,331],{"emptyLinePlaceholder":330},[318,746,748],{"class":320,"line":747},76,[318,749,750],{},"    public function getDate(): string;\n",[318,752,754],{"class":320,"line":753},77,[318,755,695],{},[318,757,759],{"class":320,"line":758},78,[318,760,331],{"emptyLinePlaceholder":330},[318,762,764],{"class":320,"line":763},79,[318,765,348],{},[318,767,769],{"class":320,"line":768},80,[318,770,771],{}," * The Concrete Memento contains the infrastructure for storing the Originator's\n",[318,773,775],{"class":320,"line":774},81,[318,776,777],{}," * state.\n",[318,779,781],{"class":320,"line":780},82,[318,782,372],{},[318,784,786],{"class":320,"line":785},83,[318,787,788],{},"class ConcreteMemento implements Memento\n",[318,790,792],{"class":320,"line":791},84,[318,793,384],{},[318,795,797],{"class":320,"line":796},85,[318,798,414],{},[318,800,802],{"class":320,"line":801},86,[318,803,331],{"emptyLinePlaceholder":330},[318,805,807],{"class":320,"line":806},87,[318,808,809],{},"    private $date;\n",[318,811,813],{"class":320,"line":812},88,[318,814,331],{"emptyLinePlaceholder":330},[318,816,818],{"class":320,"line":817},89,[318,819,425],{},[318,821,823],{"class":320,"line":822},90,[318,824,431],{},[318,826,828],{"class":320,"line":827},91,[318,829,437],{},[318,831,833],{"class":320,"line":832},92,[318,834,835],{},"        $this->date = date('Y-m-d H:i:s');\n",[318,837,839],{"class":320,"line":838},93,[318,840,449],{},[318,842,844],{"class":320,"line":843},94,[318,845,331],{"emptyLinePlaceholder":330},[318,847,849],{"class":320,"line":848},95,[318,850,390],{},[318,852,854],{"class":320,"line":853},96,[318,855,856],{},"     * The Originator uses this method when restoring its state.\n",[318,858,860],{"class":320,"line":859},97,[318,861,408],{},[318,863,865],{"class":320,"line":864},98,[318,866,867],{},"    public function getState(): string\n",[318,869,871],{"class":320,"line":870},99,[318,872,431],{},[318,874,876],{"class":320,"line":875},100,[318,877,878],{},"        return $this->state;\n",[318,880,882],{"class":320,"line":881},101,[318,883,449],{},[318,885,887],{"class":320,"line":886},102,[318,888,331],{"emptyLinePlaceholder":330},[318,890,892],{"class":320,"line":891},103,[318,893,390],{},[318,895,897],{"class":320,"line":896},104,[318,898,899],{},"     * The rest of the methods are used by the Caretaker to display metadata.\n",[318,901,903],{"class":320,"line":902},105,[318,904,408],{},[318,906,908],{"class":320,"line":907},106,[318,909,910],{},"    public function getName(): string\n",[318,912,914],{"class":320,"line":913},107,[318,915,431],{},[318,917,919],{"class":320,"line":918},108,[318,920,921],{},"        return $this->date . \" \u002F (\" . substr($this->state, 0, 9) . \"...)\";\n",[318,923,925],{"class":320,"line":924},109,[318,926,449],{},[318,928,930],{"class":320,"line":929},110,[318,931,331],{"emptyLinePlaceholder":330},[318,933,935],{"class":320,"line":934},111,[318,936,937],{},"    public function getDate(): string\n",[318,939,941],{"class":320,"line":940},112,[318,942,431],{},[318,944,946],{"class":320,"line":945},113,[318,947,948],{},"        return $this->date;\n",[318,950,952],{"class":320,"line":951},114,[318,953,449],{},[318,955,957],{"class":320,"line":956},115,[318,958,695],{},[318,960,962],{"class":320,"line":961},116,[318,963,331],{"emptyLinePlaceholder":330},[318,965,967],{"class":320,"line":966},117,[318,968,348],{},[318,970,972],{"class":320,"line":971},118,[318,973,974],{}," * The Caretaker doesn't depend on the Concrete Memento class. Therefore, it\n",[318,976,978],{"class":320,"line":977},119,[318,979,980],{}," * doesn't have access to the originator's state, stored inside the memento. It\n",[318,982,984],{"class":320,"line":983},120,[318,985,986],{}," * works with all mementos via the base Memento interface.\n",[318,988,990],{"class":320,"line":989},121,[318,991,372],{},[318,993,995],{"class":320,"line":994},122,[318,996,997],{},"class Caretaker\n",[318,999,1001],{"class":320,"line":1000},123,[318,1002,384],{},[318,1004,1006],{"class":320,"line":1005},124,[318,1007,390],{},[318,1009,1011],{"class":320,"line":1010},125,[318,1012,1013],{},"     * @var Memento[]\n",[318,1015,1017],{"class":320,"line":1016},126,[318,1018,408],{},[318,1020,1022],{"class":320,"line":1021},127,[318,1023,1024],{},"    private $mementos = [];\n",[318,1026,1028],{"class":320,"line":1027},128,[318,1029,331],{"emptyLinePlaceholder":330},[318,1031,1033],{"class":320,"line":1032},129,[318,1034,390],{},[318,1036,1038],{"class":320,"line":1037},130,[318,1039,1040],{},"     * @var Originator\n",[318,1042,1044],{"class":320,"line":1043},131,[318,1045,408],{},[318,1047,1049],{"class":320,"line":1048},132,[318,1050,1051],{},"    private $originator;\n",[318,1053,1055],{"class":320,"line":1054},133,[318,1056,331],{"emptyLinePlaceholder":330},[318,1058,1060],{"class":320,"line":1059},134,[318,1061,1062],{},"    public function __construct(Originator $originator)\n",[318,1064,1066],{"class":320,"line":1065},135,[318,1067,431],{},[318,1069,1071],{"class":320,"line":1070},136,[318,1072,1073],{},"        $this->originator = $originator;\n",[318,1075,1077],{"class":320,"line":1076},137,[318,1078,449],{},[318,1080,1082],{"class":320,"line":1081},138,[318,1083,331],{"emptyLinePlaceholder":330},[318,1085,1087],{"class":320,"line":1086},139,[318,1088,1089],{},"    public function backup(): void\n",[318,1091,1093],{"class":320,"line":1092},140,[318,1094,431],{},[318,1096,1098],{"class":320,"line":1097},141,[318,1099,1100],{},"        echo \"\\nCaretaker: Saving Originator's state...\\n\";\n",[318,1102,1104],{"class":320,"line":1103},142,[318,1105,1106],{},"        $this->mementos[] = $this->originator->save();\n",[318,1108,1110],{"class":320,"line":1109},143,[318,1111,449],{},[318,1113,1115],{"class":320,"line":1114},144,[318,1116,331],{"emptyLinePlaceholder":330},[318,1118,1120],{"class":320,"line":1119},145,[318,1121,1122],{},"    public function undo(): void\n",[318,1124,1126],{"class":320,"line":1125},146,[318,1127,431],{},[318,1129,1131],{"class":320,"line":1130},147,[318,1132,1133],{},"        if (!count($this->mementos)) {\n",[318,1135,1137],{"class":320,"line":1136},148,[318,1138,1139],{},"            return;\n",[318,1141,1143],{"class":320,"line":1142},149,[318,1144,1145],{},"        }\n",[318,1147,1149],{"class":320,"line":1148},150,[318,1150,1151],{},"        $memento = array_pop($this->mementos);\n",[318,1153,1155],{"class":320,"line":1154},151,[318,1156,331],{"emptyLinePlaceholder":330},[318,1158,1160],{"class":320,"line":1159},152,[318,1161,1162],{},"        echo \"Caretaker: Restoring state to: \" . $memento->getName() . \"\\n\";\n",[318,1164,1166],{"class":320,"line":1165},153,[318,1167,1168],{},"        try {\n",[318,1170,1172],{"class":320,"line":1171},154,[318,1173,1174],{},"            $this->originator->restore($memento);\n",[318,1176,1178],{"class":320,"line":1177},155,[318,1179,1180],{},"        } catch (\\Exception $e) {\n",[318,1182,1184],{"class":320,"line":1183},156,[318,1185,1186],{},"            $this->undo();\n",[318,1188,1190],{"class":320,"line":1189},157,[318,1191,1145],{},[318,1193,1195],{"class":320,"line":1194},158,[318,1196,449],{},[318,1198,1200],{"class":320,"line":1199},159,[318,1201,331],{"emptyLinePlaceholder":330},[318,1203,1205],{"class":320,"line":1204},160,[318,1206,1207],{},"    public function showHistory(): void\n",[318,1209,1211],{"class":320,"line":1210},161,[318,1212,431],{},[318,1214,1216],{"class":320,"line":1215},162,[318,1217,1218],{},"        echo \"Caretaker: Here's the list of mementos:\\n\";\n",[318,1220,1222],{"class":320,"line":1221},163,[318,1223,1224],{},"        foreach ($this->mementos as $memento) {\n",[318,1226,1228],{"class":320,"line":1227},164,[318,1229,1230],{},"            echo $memento->getName() . \"\\n\";\n",[318,1232,1234],{"class":320,"line":1233},165,[318,1235,1145],{},[318,1237,1239],{"class":320,"line":1238},166,[318,1240,449],{},[318,1242,1244],{"class":320,"line":1243},167,[318,1245,695],{},[318,1247,1249],{"class":320,"line":1248},168,[318,1250,331],{"emptyLinePlaceholder":330},[318,1252,1254],{"class":320,"line":1253},169,[318,1255,348],{},[318,1257,1259],{"class":320,"line":1258},170,[318,1260,1261],{}," * Client code.\n",[318,1263,1265],{"class":320,"line":1264},171,[318,1266,372],{},[318,1268,1270],{"class":320,"line":1269},172,[318,1271,1272],{},"$originator = new Originator(\"Super-duper-super-puper-super.\");\n",[318,1274,1276],{"class":320,"line":1275},173,[318,1277,1278],{},"$caretaker = new Caretaker($originator);\n",[318,1280,1282],{"class":320,"line":1281},174,[318,1283,331],{"emptyLinePlaceholder":330},[318,1285,1287],{"class":320,"line":1286},175,[318,1288,1289],{},"$caretaker->backup();\n",[318,1291,1293],{"class":320,"line":1292},176,[318,1294,1295],{},"$originator->doSomething();\n",[318,1297,1299],{"class":320,"line":1298},177,[318,1300,331],{"emptyLinePlaceholder":330},[318,1302,1304],{"class":320,"line":1303},178,[318,1305,1289],{},[318,1307,1309],{"class":320,"line":1308},179,[318,1310,1295],{},[318,1312,1314],{"class":320,"line":1313},180,[318,1315,331],{"emptyLinePlaceholder":330},[318,1317,1319],{"class":320,"line":1318},181,[318,1320,1289],{},[318,1322,1324],{"class":320,"line":1323},182,[318,1325,1295],{},[318,1327,1329],{"class":320,"line":1328},183,[318,1330,331],{"emptyLinePlaceholder":330},[318,1332,1334],{"class":320,"line":1333},184,[318,1335,1336],{},"echo \"\\n\";\n",[318,1338,1340],{"class":320,"line":1339},185,[318,1341,1342],{},"$caretaker->showHistory();\n",[318,1344,1346],{"class":320,"line":1345},186,[318,1347,331],{"emptyLinePlaceholder":330},[318,1349,1351],{"class":320,"line":1350},187,[318,1352,1353],{},"echo \"\\nClient: Now, let's rollback!\\n\\n\";\n",[318,1355,1357],{"class":320,"line":1356},188,[318,1358,1359],{},"$caretaker->undo();\n",[318,1361,1363],{"class":320,"line":1362},189,[318,1364,331],{"emptyLinePlaceholder":330},[318,1366,1368],{"class":320,"line":1367},190,[318,1369,1370],{},"echo \"\\nClient: Once more!\\n\\n\";\n",[318,1372,1374],{"class":320,"line":1373},191,[318,1375,1359],{},[166,1377,1379],{"id":1378},"örnek-python-kodu","Örnek Python Kodu",[309,1381,1385],{"className":1382,"code":1383,"language":1384,"meta":314,"style":314},"language-python shiki shiki-themes github-light github-dark","from __future__ import annotations\nfrom abc import ABC, abstractmethod\nfrom datetime import datetime\nfrom random import sample\nfrom string import ascii_letters, digits\n\nclass Originator():\n    \"\"\"\n    The Originator holds some important state that may change over time. It also\n    defines a method for saving the state inside a memento and another method\n    for restoring the state from it.\n    \"\"\"\n\n    _state = None\n    \"\"\"\n    For the sake of simplicity, the originator's state is stored inside a single\n    variable.\n    \"\"\"\n\n    def __init__(self, state: str) -> None:\n        self._state = state\n        print(f\"Originator: My initial state is: {self._state}\")\n\n    def do_something(self) -> None:\n        \"\"\"\n        The Originator's business logic may affect its internal state.\n        Therefore, the client should backup the state before launching methods\n        of the business logic via the save() method.\n        \"\"\"\n\n        print(\"Originator: I'm doing something important.\")\n        self._state = self._generate_random_string(30)\n        print(f\"Originator: and my state has changed to: {self._state}\")\n\n    def _generate_random_string(self, length: int = 10) -> None:\n        return \"\".join(sample(ascii_letters, length))\n\n    def save(self) -> Memento:\n        \"\"\"\n        Saves the current state inside a memento.\n        \"\"\"\n\n        return ConcreteMemento(self._state)\n\n    def restore(self, memento: Memento) -> None:\n        \"\"\"\n        Restores the Originator's state from a memento object.\n        \"\"\"\n\n        self._state = memento.get_state()\n        print(f\"Originator: My state has changed to: {self._state}\")\n\nclass Memento(ABC):\n    \"\"\"\n    The Memento interface provides a way to retrieve the memento's metadata,\n    such as creation date or name. However, it doesn't expose the Originator's\n    state.\n    \"\"\"\n\n    @abstractmethod\n    def get_name(self) -> str:\n        pass\n\n    @abstractmethod\n    def get_date(self) -> str:\n        pass\n\nclass ConcreteMemento(Memento):\n    def __init__(self, state: str) -> None:\n        self._state = state\n        self._date = str(datetime.now())[:19]\n\n    def get_state(self) -> str:\n        \"\"\"\n        The Originator uses this method when restoring its state.\n        \"\"\"\n        return self._state\n\n    def get_name(self) -> str:\n        \"\"\"\n        The rest of the methods are used by the Caretaker to display metadata.\n        \"\"\"\n\n        return f\"{self._date} \u002F ({self._state[0:9]}...)\"\n\n    def get_date(self) -> str:\n        return self._date\n\nclass Caretaker():\n    \"\"\"\n    The Caretaker doesn't depend on the Concrete Memento class. Therefore, it\n    doesn't have access to the originator's state, stored inside the memento. It\n    works with all mementos via the base Memento interface.\n    \"\"\"\n\n    def __init__(self, originator: Originator) -> None:\n        self._mementos = []\n        self._originator = originator\n\n    def backup(self) -> None:\n        print(\"\\nCaretaker: Saving Originator's state...\")\n        self._mementos.append(self._originator.save())\n\n    def undo(self) -> None:\n        if not len(self._mementos):\n            return\n\n        memento = self._mementos.pop()\n        print(f\"Caretaker: Restoring state to: {memento.get_name()}\")\n        try:\n            self._originator.restore(memento)\n        except Exception:\n            self.undo()\n\n    def show_history(self) -> None:\n        print(\"Caretaker: Here's the list of mementos:\")\n        for memento in self._mementos:\n            print(memento.get_name())\n\nif __name__ == \"__main__\":\n    originator = Originator(\"Super-duper-super-puper-super.\")\n    caretaker = Caretaker(originator)\n\n    caretaker.backup()\n    originator.do_something()\n\n    caretaker.backup()\n    originator.do_something()\n\n    caretaker.backup()\n    originator.do_something()\n\n    print()\n    caretaker.show_history()\n\n    print(\"\\nClient: Now, let's rollback!\\n\")\n    caretaker.undo()\n\n    print(\"\\nClient: Once more!\\n\")\n    caretaker.undo()\n","python",[44,1386,1387,1392,1397,1402,1407,1412,1416,1421,1426,1431,1436,1441,1445,1449,1454,1458,1463,1468,1472,1476,1481,1486,1491,1495,1500,1505,1510,1515,1520,1524,1528,1533,1538,1543,1547,1552,1557,1561,1566,1570,1575,1579,1583,1588,1592,1597,1601,1606,1610,1614,1619,1624,1628,1633,1637,1642,1647,1652,1656,1660,1665,1670,1675,1679,1683,1688,1692,1696,1701,1705,1709,1714,1718,1723,1727,1732,1736,1741,1745,1749,1753,1758,1762,1766,1771,1775,1779,1784,1788,1793,1797,1802,1807,1812,1816,1820,1825,1830,1835,1839,1844,1849,1854,1858,1863,1868,1873,1877,1882,1887,1892,1897,1902,1907,1911,1916,1921,1926,1931,1935,1940,1945,1950,1954,1959,1964,1968,1972,1976,1980,1984,1988,1992,1997,2002,2006,2011,2016,2020,2025],{"__ignoreMap":314},[318,1388,1389],{"class":320,"line":321},[318,1390,1391],{},"from __future__ import annotations\n",[318,1393,1394],{"class":320,"line":327},[318,1395,1396],{},"from abc import ABC, abstractmethod\n",[318,1398,1399],{"class":320,"line":334},[318,1400,1401],{},"from datetime import datetime\n",[318,1403,1404],{"class":320,"line":340},[318,1405,1406],{},"from random import sample\n",[318,1408,1409],{"class":320,"line":345},[318,1410,1411],{},"from string import ascii_letters, digits\n",[318,1413,1414],{"class":320,"line":351},[318,1415,331],{"emptyLinePlaceholder":330},[318,1417,1418],{"class":320,"line":357},[318,1419,1420],{},"class Originator():\n",[318,1422,1423],{"class":320,"line":363},[318,1424,1425],{},"    \"\"\"\n",[318,1427,1428],{"class":320,"line":369},[318,1429,1430],{},"    The Originator holds some important state that may change over time. It also\n",[318,1432,1433],{"class":320,"line":375},[318,1434,1435],{},"    defines a method for saving the state inside a memento and another method\n",[318,1437,1438],{"class":320,"line":381},[318,1439,1440],{},"    for restoring the state from it.\n",[318,1442,1443],{"class":320,"line":387},[318,1444,1425],{},[318,1446,1447],{"class":320,"line":393},[318,1448,331],{"emptyLinePlaceholder":330},[318,1450,1451],{"class":320,"line":399},[318,1452,1453],{},"    _state = None\n",[318,1455,1456],{"class":320,"line":405},[318,1457,1425],{},[318,1459,1460],{"class":320,"line":411},[318,1461,1462],{},"    For the sake of simplicity, the originator's state is stored inside a single\n",[318,1464,1465],{"class":320,"line":417},[318,1466,1467],{},"    variable.\n",[318,1469,1470],{"class":320,"line":422},[318,1471,1425],{},[318,1473,1474],{"class":320,"line":428},[318,1475,331],{"emptyLinePlaceholder":330},[318,1477,1478],{"class":320,"line":434},[318,1479,1480],{},"    def __init__(self, state: str) -> None:\n",[318,1482,1483],{"class":320,"line":440},[318,1484,1485],{},"        self._state = state\n",[318,1487,1488],{"class":320,"line":446},[318,1489,1490],{},"        print(f\"Originator: My initial state is: {self._state}\")\n",[318,1492,1493],{"class":320,"line":452},[318,1494,331],{"emptyLinePlaceholder":330},[318,1496,1497],{"class":320,"line":457},[318,1498,1499],{},"    def do_something(self) -> None:\n",[318,1501,1502],{"class":320,"line":462},[318,1503,1504],{},"        \"\"\"\n",[318,1506,1507],{"class":320,"line":468},[318,1508,1509],{},"        The Originator's business logic may affect its internal state.\n",[318,1511,1512],{"class":320,"line":474},[318,1513,1514],{},"        Therefore, the client should backup the state before launching methods\n",[318,1516,1517],{"class":320,"line":480},[318,1518,1519],{},"        of the business logic via the save() method.\n",[318,1521,1522],{"class":320,"line":485},[318,1523,1504],{},[318,1525,1526],{"class":320,"line":491},[318,1527,331],{"emptyLinePlaceholder":330},[318,1529,1530],{"class":320,"line":496},[318,1531,1532],{},"        print(\"Originator: I'm doing something important.\")\n",[318,1534,1535],{"class":320,"line":502},[318,1536,1537],{},"        self._state = self._generate_random_string(30)\n",[318,1539,1540],{"class":320,"line":508},[318,1541,1542],{},"        print(f\"Originator: and my state has changed to: {self._state}\")\n",[318,1544,1545],{"class":320,"line":514},[318,1546,331],{"emptyLinePlaceholder":330},[318,1548,1549],{"class":320,"line":519},[318,1550,1551],{},"    def _generate_random_string(self, length: int = 10) -> None:\n",[318,1553,1554],{"class":320,"line":524},[318,1555,1556],{},"        return \"\".join(sample(ascii_letters, length))\n",[318,1558,1559],{"class":320,"line":530},[318,1560,331],{"emptyLinePlaceholder":330},[318,1562,1563],{"class":320,"line":535},[318,1564,1565],{},"    def save(self) -> Memento:\n",[318,1567,1568],{"class":320,"line":541},[318,1569,1504],{},[318,1571,1572],{"class":320,"line":547},[318,1573,1574],{},"        Saves the current state inside a memento.\n",[318,1576,1577],{"class":320,"line":553},[318,1578,1504],{},[318,1580,1581],{"class":320,"line":559},[318,1582,331],{"emptyLinePlaceholder":330},[318,1584,1585],{"class":320,"line":565},[318,1586,1587],{},"        return ConcreteMemento(self._state)\n",[318,1589,1590],{"class":320,"line":571},[318,1591,331],{"emptyLinePlaceholder":330},[318,1593,1594],{"class":320,"line":577},[318,1595,1596],{},"    def restore(self, memento: Memento) -> None:\n",[318,1598,1599],{"class":320,"line":583},[318,1600,1504],{},[318,1602,1603],{"class":320,"line":589},[318,1604,1605],{},"        Restores the Originator's state from a memento object.\n",[318,1607,1608],{"class":320,"line":595},[318,1609,1504],{},[318,1611,1612],{"class":320,"line":600},[318,1613,331],{"emptyLinePlaceholder":330},[318,1615,1616],{"class":320,"line":605},[318,1617,1618],{},"        self._state = memento.get_state()\n",[318,1620,1621],{"class":320,"line":610},[318,1622,1623],{},"        print(f\"Originator: My state has changed to: {self._state}\")\n",[318,1625,1626],{"class":320,"line":616},[318,1627,331],{"emptyLinePlaceholder":330},[318,1629,1630],{"class":320,"line":621},[318,1631,1632],{},"class Memento(ABC):\n",[318,1634,1635],{"class":320,"line":627},[318,1636,1425],{},[318,1638,1639],{"class":320,"line":632},[318,1640,1641],{},"    The Memento interface provides a way to retrieve the memento's metadata,\n",[318,1643,1644],{"class":320,"line":638},[318,1645,1646],{},"    such as creation date or name. However, it doesn't expose the Originator's\n",[318,1648,1649],{"class":320,"line":643},[318,1650,1651],{},"    state.\n",[318,1653,1654],{"class":320,"line":648},[318,1655,1425],{},[318,1657,1658],{"class":320,"line":653},[318,1659,331],{"emptyLinePlaceholder":330},[318,1661,1662],{"class":320,"line":659},[318,1663,1664],{},"    @abstractmethod\n",[318,1666,1667],{"class":320,"line":664},[318,1668,1669],{},"    def get_name(self) -> str:\n",[318,1671,1672],{"class":320,"line":670},[318,1673,1674],{},"        pass\n",[318,1676,1677],{"class":320,"line":675},[318,1678,331],{"emptyLinePlaceholder":330},[318,1680,1681],{"class":320,"line":681},[318,1682,1664],{},[318,1684,1685],{"class":320,"line":687},[318,1686,1687],{},"    def get_date(self) -> str:\n",[318,1689,1690],{"class":320,"line":692},[318,1691,1674],{},[318,1693,1694],{"class":320,"line":698},[318,1695,331],{"emptyLinePlaceholder":330},[318,1697,1698],{"class":320,"line":703},[318,1699,1700],{},"class ConcreteMemento(Memento):\n",[318,1702,1703],{"class":320,"line":708},[318,1704,1480],{},[318,1706,1707],{"class":320,"line":714},[318,1708,1485],{},[318,1710,1711],{"class":320,"line":720},[318,1712,1713],{},"        self._date = str(datetime.now())[:19]\n",[318,1715,1716],{"class":320,"line":725},[318,1717,331],{"emptyLinePlaceholder":330},[318,1719,1720],{"class":320,"line":731},[318,1721,1722],{},"    def get_state(self) -> str:\n",[318,1724,1725],{"class":320,"line":736},[318,1726,1504],{},[318,1728,1729],{"class":320,"line":742},[318,1730,1731],{},"        The Originator uses this method when restoring its state.\n",[318,1733,1734],{"class":320,"line":747},[318,1735,1504],{},[318,1737,1738],{"class":320,"line":753},[318,1739,1740],{},"        return self._state\n",[318,1742,1743],{"class":320,"line":758},[318,1744,331],{"emptyLinePlaceholder":330},[318,1746,1747],{"class":320,"line":763},[318,1748,1669],{},[318,1750,1751],{"class":320,"line":768},[318,1752,1504],{},[318,1754,1755],{"class":320,"line":774},[318,1756,1757],{},"        The rest of the methods are used by the Caretaker to display metadata.\n",[318,1759,1760],{"class":320,"line":780},[318,1761,1504],{},[318,1763,1764],{"class":320,"line":785},[318,1765,331],{"emptyLinePlaceholder":330},[318,1767,1768],{"class":320,"line":791},[318,1769,1770],{},"        return f\"{self._date} \u002F ({self._state[0:9]}...)\"\n",[318,1772,1773],{"class":320,"line":796},[318,1774,331],{"emptyLinePlaceholder":330},[318,1776,1777],{"class":320,"line":801},[318,1778,1687],{},[318,1780,1781],{"class":320,"line":806},[318,1782,1783],{},"        return self._date\n",[318,1785,1786],{"class":320,"line":812},[318,1787,331],{"emptyLinePlaceholder":330},[318,1789,1790],{"class":320,"line":817},[318,1791,1792],{},"class Caretaker():\n",[318,1794,1795],{"class":320,"line":822},[318,1796,1425],{},[318,1798,1799],{"class":320,"line":827},[318,1800,1801],{},"    The Caretaker doesn't depend on the Concrete Memento class. Therefore, it\n",[318,1803,1804],{"class":320,"line":832},[318,1805,1806],{},"    doesn't have access to the originator's state, stored inside the memento. It\n",[318,1808,1809],{"class":320,"line":838},[318,1810,1811],{},"    works with all mementos via the base Memento interface.\n",[318,1813,1814],{"class":320,"line":843},[318,1815,1425],{},[318,1817,1818],{"class":320,"line":848},[318,1819,331],{"emptyLinePlaceholder":330},[318,1821,1822],{"class":320,"line":853},[318,1823,1824],{},"    def __init__(self, originator: Originator) -> None:\n",[318,1826,1827],{"class":320,"line":859},[318,1828,1829],{},"        self._mementos = []\n",[318,1831,1832],{"class":320,"line":864},[318,1833,1834],{},"        self._originator = originator\n",[318,1836,1837],{"class":320,"line":870},[318,1838,331],{"emptyLinePlaceholder":330},[318,1840,1841],{"class":320,"line":875},[318,1842,1843],{},"    def backup(self) -> None:\n",[318,1845,1846],{"class":320,"line":881},[318,1847,1848],{},"        print(\"\\nCaretaker: Saving Originator's state...\")\n",[318,1850,1851],{"class":320,"line":886},[318,1852,1853],{},"        self._mementos.append(self._originator.save())\n",[318,1855,1856],{"class":320,"line":891},[318,1857,331],{"emptyLinePlaceholder":330},[318,1859,1860],{"class":320,"line":896},[318,1861,1862],{},"    def undo(self) -> None:\n",[318,1864,1865],{"class":320,"line":902},[318,1866,1867],{},"        if not len(self._mementos):\n",[318,1869,1870],{"class":320,"line":907},[318,1871,1872],{},"            return\n",[318,1874,1875],{"class":320,"line":913},[318,1876,331],{"emptyLinePlaceholder":330},[318,1878,1879],{"class":320,"line":918},[318,1880,1881],{},"        memento = self._mementos.pop()\n",[318,1883,1884],{"class":320,"line":924},[318,1885,1886],{},"        print(f\"Caretaker: Restoring state to: {memento.get_name()}\")\n",[318,1888,1889],{"class":320,"line":929},[318,1890,1891],{},"        try:\n",[318,1893,1894],{"class":320,"line":934},[318,1895,1896],{},"            self._originator.restore(memento)\n",[318,1898,1899],{"class":320,"line":940},[318,1900,1901],{},"        except Exception:\n",[318,1903,1904],{"class":320,"line":945},[318,1905,1906],{},"            self.undo()\n",[318,1908,1909],{"class":320,"line":951},[318,1910,331],{"emptyLinePlaceholder":330},[318,1912,1913],{"class":320,"line":956},[318,1914,1915],{},"    def show_history(self) -> None:\n",[318,1917,1918],{"class":320,"line":961},[318,1919,1920],{},"        print(\"Caretaker: Here's the list of mementos:\")\n",[318,1922,1923],{"class":320,"line":966},[318,1924,1925],{},"        for memento in self._mementos:\n",[318,1927,1928],{"class":320,"line":971},[318,1929,1930],{},"            print(memento.get_name())\n",[318,1932,1933],{"class":320,"line":977},[318,1934,331],{"emptyLinePlaceholder":330},[318,1936,1937],{"class":320,"line":983},[318,1938,1939],{},"if __name__ == \"__main__\":\n",[318,1941,1942],{"class":320,"line":989},[318,1943,1944],{},"    originator = Originator(\"Super-duper-super-puper-super.\")\n",[318,1946,1947],{"class":320,"line":994},[318,1948,1949],{},"    caretaker = Caretaker(originator)\n",[318,1951,1952],{"class":320,"line":1000},[318,1953,331],{"emptyLinePlaceholder":330},[318,1955,1956],{"class":320,"line":1005},[318,1957,1958],{},"    caretaker.backup()\n",[318,1960,1961],{"class":320,"line":1010},[318,1962,1963],{},"    originator.do_something()\n",[318,1965,1966],{"class":320,"line":1016},[318,1967,331],{"emptyLinePlaceholder":330},[318,1969,1970],{"class":320,"line":1021},[318,1971,1958],{},[318,1973,1974],{"class":320,"line":1027},[318,1975,1963],{},[318,1977,1978],{"class":320,"line":1032},[318,1979,331],{"emptyLinePlaceholder":330},[318,1981,1982],{"class":320,"line":1037},[318,1983,1958],{},[318,1985,1986],{"class":320,"line":1043},[318,1987,1963],{},[318,1989,1990],{"class":320,"line":1048},[318,1991,331],{"emptyLinePlaceholder":330},[318,1993,1994],{"class":320,"line":1054},[318,1995,1996],{},"    print()\n",[318,1998,1999],{"class":320,"line":1059},[318,2000,2001],{},"    caretaker.show_history()\n",[318,2003,2004],{"class":320,"line":1065},[318,2005,331],{"emptyLinePlaceholder":330},[318,2007,2008],{"class":320,"line":1070},[318,2009,2010],{},"    print(\"\\nClient: Now, let's rollback!\\n\")\n",[318,2012,2013],{"class":320,"line":1076},[318,2014,2015],{},"    caretaker.undo()\n",[318,2017,2018],{"class":320,"line":1081},[318,2019,331],{"emptyLinePlaceholder":330},[318,2021,2022],{"class":320,"line":1086},[318,2023,2024],{},"    print(\"\\nClient: Once more!\\n\")\n",[318,2026,2027],{"class":320,"line":1092},[318,2028,2015],{},[74,2030],{},[77,2032,2034],{"id":2033},"diğer-tasarım-kalıplarıdesign-patterns","Diğer Tasarım Kalıpları\u002FDesign Patterns",[14,2036,2037],{},[18,2038,2039],{},"Oluşumsal Kalıplar (Creational Patterns)",[14,2041,2042,2046,2047,2046,2051,2046,2055,2046,2058],{},[52,2043,2045],{"href":2044},"\u002Ftr\u002Ftasarim-kaliplari-design-patterns-factory-method-nedir","Factory Method",",\n",[52,2048,2050],{"href":2049},"\u002Ftr\u002Ftasarim-kaliplari-design-patterns-abstract-factory-nedir","Abstract Factory",[52,2052,2054],{"href":2053},"\u002Ftr\u002Fbuilder-tasarim-deseni-nedir","Builder",[52,2056,293],{"href":2057},"\u002Ftr\u002Fprototype-tasarim-deseni-nedir",[52,2059,2061],{"href":2060},"\u002Ftr\u002Fsingleton-tasarim-deseni-nedir","Singleton",[14,2063,2064],{},[18,2065,2066],{},"Yapısal Kalıplar (Structural Patterns)",[14,2068,2069,2046,2073,2046,2077,2046,2081,2046,2085,2046,2089,2046,2093],{},[52,2070,2072],{"href":2071},"\u002Ftr\u002Fadapter-tasarim-deseni-nedir","Adapter",[52,2074,2076],{"href":2075},"\u002Ftr\u002Fbridge-tasarim-deseni-nedir","Bridge",[52,2078,2080],{"href":2079},"\u002Ftr\u002Fcomposite-tasarim-deseni-nedir","Composite",[52,2082,2084],{"href":2083},"\u002Ftr\u002Fdecorator-tasarim-deseni-nedir","Decorator",[52,2086,2088],{"href":2087},"\u002Ftr\u002Ffacade-tasarim-deseni-nedir","Facade",[52,2090,2092],{"href":2091},"\u002Ftr\u002Fflyweight-tasarim-deseni-nedir","Flyweight",[52,2094,2096],{"href":2095},"\u002Ftr\u002Fproxy-tasarim-deseni-nedir","Proxy",[14,2098,2099],{},[18,2100,2101],{},"Davranışsal Kalıplar (Behavioral Patterns)",[14,2103,2104,2046,2108,2046,2111,2046,2114,2046,2118,2046,2121,2046,2125,2046,2129,2046,2133,2046,2137],{},[52,2105,2107],{"href":2106},"\u002Ftr\u002Fchain-of-responsibility-deseni-nedir","Chain of Responsibility",[52,2109,275],{"href":2110},"\u002Ftr\u002Fcommand-tasarim-deseni-nedir",[52,2112,285],{"href":2113},"\u002Ftr\u002Fiterator-tasarim-deseni-nedir",[52,2115,2117],{"href":2116},"\u002Ftr\u002Fmediator-tasarim-deseni-nedir","Mediator",[52,2119,46],{"href":2120},"\u002Ftr\u002Fmemento-tasarim-deseni-nedir",[52,2122,2124],{"href":2123},"\u002Ftr\u002Fobserver-tasarim-deseni-nedir","Observer",[52,2126,2128],{"href":2127},"\u002Ftr\u002Fstate-tasarim-deseni-nedir","State",[52,2130,2132],{"href":2131},"\u002Ftr\u002Fstrategy-tasarim-deseni-nedir","Strategy",[52,2134,2136],{"href":2135},"\u002Ftr\u002Ftemplate-method-tasarim-deseni-nedir","Template Method",[52,2138,2140],{"href":2139},"\u002Ftr\u002Fvisitor-tasarim-deseni-nedir","Visitor",[2142,2143,2144],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":314,"searchDepth":327,"depth":327,"links":2146},[2147,2148,2149,2152,2153,2154,2158],{"id":79,"depth":327,"text":80},{"id":96,"depth":327,"text":97},{"id":130,"depth":327,"text":131,"children":2150},[2151],{"id":168,"depth":334,"text":169},{"id":244,"depth":327,"text":245},{"id":266,"depth":327,"text":267},{"id":302,"depth":327,"text":303,"children":2155},[2156,2157],{"id":306,"depth":334,"text":307},{"id":1378,"depth":334,"text":1379},{"id":2033,"depth":327,"text":2034},[2160],"technical",null,"2021-10-04","Memento tasarım deseninin amacı, nesne kapsülleme (encapsulation) sınırlarını koruyarak geri alma (Undo\u002FRedo) işlemlerinin nasıl tasarlandığı.",false,"md","\u002Fimages\u002Fposts\u002F2021\u002F10\u002Fmemento-tasarim-deseni.avif",{},{"title":6,"description":2163},"memento-tasarim-deseni-nedir","tr\u002Fmemento-tasarim-deseni-nedir",[2172,2173],"design-pattern","ipucu","2f9u1-1Hi5uB0JxfWeUDZtnJ1kaE3O7dZNrL7jtzIME",{"prev":2176,"next":2179,"others":2181,"lucky":2293,"readingTime":375},{"path":2177,"title":2178},"\u002Ftr\u002Fgoda-iota-nedir-iota-ne-zaman-ve-nerede-kullanilir","Go'da iota Nedir? iota Ne Zaman ve Nerede Kullanılır?",{"path":2116,"title":2180},"Mediator Tasarım Deseni Nedir?",[2182,2185,2188,2191,2194,2197,2200,2202,2205,2208,2211,2214,2217,2220,2223,2225,2228,2231,2232,2235,2237,2240,2243,2245,2248,2251,2254,2257,2260,2263,2265,2268,2271,2274,2275,2278,2281,2284,2287,2290],{"path":2183,"title":2184},"\u002Ftr\u002Fubuntu-24-04-uzerinde-cyberpanel-kurulumu","Ubuntu 24.04 LTS ve 22.04 LTS Üzerinde CyberPanel Kurulumu",{"path":2186,"title":2187},"\u002Ftr\u002Fphp-generator-ve-iterator-farki","PHP'de Generator ve Iterator Arasındaki Temel Farklar",{"path":2189,"title":2190},"\u002Ftr\u002Flinuxda-golang-kurulumu","Linux'ta Golang Kurulumu",{"path":2192,"title":2193},"\u002Ftr\u002Fwordpress-yonetici-sifresini-wp-cli-kullanarak-sifirlama","WordPress Yönetici Şifresini WP-CLI Kullanarak Sıfırlama",{"path":2195,"title":2196},"\u002Ftr\u002Ffactory-method-ve-abstract-factory-farki-nedir","Factory Method ve Abstract Factory Farkı Nedir?",{"path":2198,"title":2199},"\u002Ftr\u002Fphp-8-0-yenilikler","Merhaba PHP 8: Modern PHP 8.x Çağı",{"path":2075,"title":2201},"Bridge Tasarım Deseni Nedir?",{"path":2203,"title":2204},"\u002Ftr\u002Fvite-nedir","Vite Nedir? Modern Web Geliştirme ve Paketleme Aracı",{"path":2206,"title":2207},"\u002Ftr\u002Fes9-nedir-ecmascript-2018-nedir","ES9 Nedir? ECMAScript 2018 Nedir?",{"path":2209,"title":2210},"\u002Ftr\u002Faws-ec2-uzerinde-docker-ve-full-stack-web-performansi","AWS EC2 Üzerinde Docker ve Full Stack Web Performansı",{"path":2212,"title":2213},"\u002Ftr\u002Flitespeed-web-server-performans-artisi","Konfor Alanından Çıkıp, Konforlu Bir VPS'e Geçmek: LiteSpeed Web Server",{"path":2215,"title":2216},"\u002Ftr\u002Fubuntu-20-04-uzerinde-cyberpanel-kurulumu","Ubuntu 20.04 üzerinde CyberPanel kurulumu",{"path":2218,"title":2219},"\u002Ftr\u002Fes10-nedir-ecmascript-2019-nedir","ES10 Nedir? ECMAScript 2019 Nedir?",{"path":2221,"title":2222},"\u002Ftr\u002Fvue-js-nedir","Vue.js Nedir? Yeni Başlayanlar İçin Rehber",{"path":2139,"title":2224},"Visitor Tasarım Deseni Nedir?",{"path":2226,"title":2227},"\u002Ftr\u002Frest-api-kimlik-dogrulama-nasil-yapilir","REST API Kimlik Doğrulama Nasıl Yapılır?",{"path":2229,"title":2230},"\u002Ftr\u002Fdigital-oceanda-vps-kurulumu","DigitalOcean'da VPS (Droplet) Kurulumu: Adım Adım Rehber",{"path":2116,"title":2180},{"path":2233,"title":2234},"\u002Ftr\u002Fgo-programlama-dilinin-ozellikleri","Go Programlama Dilinin Özellikleri",{"path":2127,"title":2236},"State Tasarım Deseni Nedir?",{"path":2238,"title":2239},"\u002Ftr\u002Fes7-nedir-ecmascript-2016-nedir","ES7 Nedir? ECMAScript 2016 Nedir?",{"path":2241,"title":2242},"\u002Ftr\u002Fgo-ve-degiskenler","Go ve Değişkenler",{"path":2123,"title":2244},"Observer Tasarım Deseni Nedir?",{"path":2246,"title":2247},"\u002Ftr\u002Frest-api-hata-yonetimi","REST Api Hata Yönetimi",{"path":2249,"title":2250},"\u002Ftr\u002Fes13-nedir-ecmascript-2022-nedir","ES13 nedir? ECMAScript 2022 nedir?",{"path":2252,"title":2253},"\u002Ftr\u002Ffull-stack-proje-agaci","Full-Stack Proje Yol Haritası ve İçindekiler",{"path":2255,"title":2256},"\u002Ftr\u002Fopenlitespeed-ve-litespeed-enterprisei-reverse-proxy-olarak-kullanmak","OpenLiteSpeed ve LiteSpeed Enterprise Sunucularını Reverse Proxy Olarak Kullanmak",{"path":2258,"title":2259},"\u002Ftr\u002Frest-api-tasarimi","REST API Tasarım İncelikleri",{"path":2261,"title":2262},"\u002Ftr\u002Fubuntu-guncellemesi-sonrasi-cyberpanele-ulasilamama-sorunlarini-giderme","Ubuntu Güncellemesi Sonrası CyberPanel'e Ulaşılamama Sorunlarını Giderme",{"path":54,"title":2264},"Design Patterns \u002F Tasarım Desenleri nedir?",{"path":2266,"title":2267},"\u002Ftr\u002Fheadless-wordpress-hakkinda-her-sey","Headless WordPress Hakkında Her Şey",{"path":2269,"title":2270},"\u002Ftr\u002Fnext-js-on-bellegi-nasil-yenilenir-on-demand-cache-regeneration","Next.js Önbelleği Nasıl Yenilenir? \"On-Demand Cache Regeneration\"",{"path":2272,"title":2273},"\u002Ftr\u002Fmerhabadunya","Merhaba Dünya",{"path":2177,"title":2178},{"path":2276,"title":2277},"\u002Ftr\u002Fdocker-ve-portainer-kurulumu","Docker ve Portainer Kurulumu",{"path":2279,"title":2280},"\u002Ftr\u002Fes5-nedir","ES5 Nedir? JavaScript Geliştiricileri İçin Kılavuz",{"path":2282,"title":2283},"\u002Ftr\u002Fubuntu-20-04-composer-kurulumu","Ubuntu 20.04 - Composer Kurulumu",{"path":2285,"title":2286},"\u002Ftr\u002Fgarbage-collection-ve-golang","Garbage Collection ve Go (Golang)",{"path":2288,"title":2289},"\u002Ftr\u002Ftailwind-css-just-in-time-modu","Tailwind CSS Just-in-Time (JIT) Modu Nedir?",{"path":2291,"title":2292},"\u002Ftr\u002Fwindows-10-golang-kurulumu","Windows 10 ve 11'de Golang Kurulumu ve GOPATH Yapılandırması",{"path":2060,"title":2294},"Singleton Tasarım Deseni Nedir?",[2296,2298,2301,2304],{"path":2139,"title":2224,"date":2297},"2021-10-09",{"path":2135,"title":2299,"date":2300},"Template Method Tasarım Deseni Nedir?","2021-10-08",{"path":2131,"title":2302,"date":2303},"Strategy Tasarım Deseni Nedir?","2021-10-07",{"path":2127,"title":2236,"date":2305},"2021-10-06",[2307,2309,2313],{"path":2261,"title":2262,"date":2308},"2023-10-14",{"path":2310,"title":2311,"date":2312},"\u002Ftr\u002Fdocker-nedir","Docker Nedir?","2021-01-06",{"path":2314,"title":2315,"date":2316},"\u002Ftr\u002Fjavascriptde-moduller","JavaScript'te Modüller","2020-12-11",1782142004922]