打游戲要存進度-備忘錄模式

打游戲要存進度-備忘錄模式

學習自

《大話設計模式》

備忘錄模式漫談

備忘錄的這種設計思想是非常常見的,比如說圍棋游戲的悔棋,繪圖軟件的撤銷功能等等,都或多或少的使用了備忘錄模式來處理對象的狀態。

備忘錄(Memento): 在不破壞封裝性的前提下,捕獲一個對象的內部狀態,并在該對象之外保存這種狀態。這樣以后就可以將該對象恢復到原來保存的狀態。

我的理解
保存好重要數據以備反悔之時使用。

備忘錄模式類圖

圖片.png | left | 787x166

  • Originator:是備忘錄的創建者
  • Memento: 是備忘錄對象
  • Caretaker: 持有備忘錄對象

沒有使用備忘錄模式的代碼

下面這一段代碼是模擬了一下,在玩游戲的時候對角色狀態的存檔與恢復。

public class GameRole
{public int Vitality { get; set; }public int Attack { get; set; }public int Defense { get; set; }public void StateDisplay(){Console.WriteLine("角色當前狀態");Console.WriteLine("體力:{0}", this.Vitality);Console.WriteLine("攻擊力:{0}", this.Attack);Console.WriteLine("防御力:{0}", this.Defense);Console.WriteLine();}public void GetInitState(){this.Vitality = 100;this.Attack = 100;this.Defense = 100;}public void Fight(){this.Vitality = 0;this.Attack = 0;this.Defense = 0;}
}static void Main(string[] args)
{GameRole gr = new GameRole();gr.GetInitState();gr.StateDisplay();//保存進度//!! 這里暴露了細節GameRole grBackup = new GameRole();grBackup.Vitality = gr.Vitality;grBackup.Attack = gr.Attack;grBackup.Defense = gr.Defense;gr.Fight();gr.StateDisplay();//回復之前的狀態//!!這里暴露的細節gr.Vitality = grBackup.Vitality;gr.Attack = grBackup.Attack;gr.Defense = grBackup.Defense;gr.StateDisplay();Console.ReadKey();
}//輸出結果
角色當前狀態
體力:100
攻擊力:100
防御力:100角色當前狀態
體力:0
攻擊力:0
防御力:0角色當前狀態
體力:100
攻擊力:100
防御力:100

上面的代碼將所有的細節暴露給了客戶端,導致客戶端承擔了太多的職責(保存狀態,恢復狀態,進行游戲),而且如果一旦游戲人物的屬性修改或者添加了,那么客戶端相關的代碼也必須修改,這些代碼緊緊地耦合在了一起。

使用了備忘錄模式的代碼

首先游戲角色這個類并不一定所有的屬性都需要備份/存檔,我們只需要把我們關系的數據進行存檔即可,為了存檔這些數據我們需要封裝起來,實現職責的分離。

public class RoleStateMemento
{public int Vitality { get; set; }public int Attack { get; set; }public int Defense { get; set; }public RoleStateMemento(int vitality, int attack, int defense){this.Vitality = vitality;this.Attack = attack;this.Defense = defense;}
}

有了存儲狀態的 Memento 對象后,我們再來修改一下 GameRole 這個類

public class GameRole
{public int Vitality { get; set; }public int Attack { get; set; }public int Defense { get; set; }public void StateDisplay(){Console.WriteLine("角色當前狀態");Console.WriteLine("體力:{0}", this.Vitality);Console.WriteLine("攻擊力:{0}", this.Attack);Console.WriteLine("防御力:{0}", this.Defense);Console.WriteLine();}public void GetInitState(){this.Vitality = 100;this.Attack = 100;this.Defense = 100;}public void Fight(){this.Vitality = 0;this.Attack = 0;this.Defense = 0;}/// <summary>/// 存檔狀態/// </summary>/// <returns></returns>public RoleStateMemento SaveRoleState(){return new RoleStateMemento(this.Vitality, this.Attack, this.Defense);}/// <summary>/// 恢復狀態/// </summary>/// <param name="memento"></param>public void RecoveryState(RoleStateMemento memento){this.Vitality = memento.Vitality;this.Attack = memento.Attack;this.Defense = memento.Defense;}
}

上面的代碼向較于最初的版本多出了兩個方法 SaveRoleStateRecoveryState 用來保存當前的角色狀態和恢復角色的狀態。

現在我們還差一個Memento的持有者

public class RoleStateCaretaker
{public RoleStateMemento RoleStateMemento { get; set; }
}

接下來我們看看客戶端的調用

static void Main(string[] args)
{GameRole gr = new GameRole();gr.GetInitState();gr.StateDisplay();//存檔RoleStateCaretaker caretaker = new RoleStateCaretaker();caretaker.RoleStateMemento = gr.SaveRoleState();//進行游戲gr.Fight();gr.StateDisplay();//恢復狀態 gr.RecoveryState(caretaker.RoleStateMemento);gr.StateDisplay();Console.ReadKey();
}
//輸出結果
角色當前狀態
體力:100
攻擊力:100
防御力:100角色當前狀態
體力:0
攻擊力:0
防御力:0角色當前狀態
體力:100
攻擊力:100
防御力:100

現在客戶端已經無法觀察到保存狀態和恢復狀態的細節了,所有的細節都被封裝到了類中,現在如果對保存/恢復狀態的業務進行修改,也不會影響到客戶端的代碼。

備忘錄模式的弊端

如果備忘錄模式需要存儲的狀態數據非常多的話,那么就會非常消耗內存。

轉載于:https://www.cnblogs.com/slyfox/p/9296938.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/282791.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/282791.shtml
英文地址,請注明出處:http://en.pswp.cn/news/282791.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

(10.1)Python學習筆記二

1、在項目工程中要模塊化測試一個開發的功能&#xff0c;在測試通過后交付給項目組其他人員繼續開發。要保證代碼開發的性能和效率以及可擴展性。 2、項目工程中的文件夾分類要功能模塊明確清晰&#xff0c;在python中引入某一個 文件夾下的文件可以使用如下方式&#xff1a; t…

利用lay-ui結合ajax實現分頁功能(不借助框架,簡單易懂)

效果圖: 1.創建html頁面 01.html(前臺文件) 2.創建index.php(后臺文件) ------------------熱身結束,開始正式分頁之旅------------------ 3.在html頁面中引入layui需要用到的css以及js,還有我們自己額外需要用到的jquery 4.在html文件中,將基本的分頁欄顯示出來 5.好啦,htm…

Linux系統壓縮及解壓縮

Linux系統解壓縮概述&#xff1a;本篇將介紹Linux系統中的壓縮和解壓縮的工具&#xff0c;以及歸檔工具&#xff08;tar&#xff0c;cpio&#xff09;compress/uncompress&#xff1a;對應 .Z 結尾的壓縮格式文件&#xff1b;gzip/gunzip&#xff1a;其對應的是 .gz 結尾的壓縮…

酷派手機android版本,系統版本迎來升級

系統版本迎來升級這個應該是兩個版本之間最大但是卻不那么直觀的不同了&#xff0c;因為從TD版酷派大神F1采用的CoolLife UI 5.0版本&#xff0c;再到聯通版酷派大神F1所搭載的CoolLife UI 5.5版本&#xff0c;它們之間經歷了一個比較不錯的升級。在圖標ICON&#xff0c;功能設…

學習RUNOOB.COM進度一

了解MongoDB 由C語言編寫的&#xff0c;是一個基于分布式文件存儲的開源數據庫系統。在高負載的情況下&#xff0c;添加更多的節點&#xff0c;可以保證服務器性能。 特點 面向文檔&#xff0c;操作簡單容易 設置任何索引&#xff0c;實現更快排序 本地或者網絡創建數據鏡像&am…

最終用戶計算安全——特權訪問控制

本篇算是系列的第二篇&#xff0c;之前寫了一篇關于勒索軟件攻擊的&#xff0c;坦白說寫這樣的文很費腦子&#xff0c;而且喜歡看的讀者估計也不多…不過我覺得整理一下思路&#xff0c;對于通過最終用戶計算產品或方案來提升組織安全還是有很大的意義的。所以一邊喝著清茶吃著…

MVC學習九:MVC 特性本質

一、特性的本質就是&#xff1a;對屬性、方法、類加特性&#xff0c;本質就是new 一個特性類對象賦值給屬性、方法、類。 可以通過反射的方式取得特性的值&#xff0c;代碼如下&#xff1a; ①自定義特性 public class MyAttribute:Attribute{public string Name { get; set; }…

前端知識點總結---面試專用

1.關于基礎css html js部分 1.1基本算法 1&#xff09;快速排序 時間復雜度 nlogn function quickSort(arr){if (arr.length<1){return arr;}var pivotIndex 0,pivort arr.splice(pivortIndex, 1)[0];var left [],right [];for (var i 1, length arr.length; i < l…

鴻蒙系統大疆,華為操作系統“鴻蒙OS”來了!

原標題&#xff1a;華為操作系統“鴻蒙OS”來了&#xff01;8月9日&#xff0c;華為消費者業務CEO余承東在華為開發者大會上如期發布了華為鴻蒙操作系統“HarmonyOS”。據介紹&#xff0c;鴻蒙內核在2017年便完成技術驗證&#xff0c;最初是為了提升操作系統的跨平臺能力而研發…

詳述 IntelliJ IDEA 插件的安裝及使用方法

首先&#xff0c;進入插件安裝界面&#xff1a; Mac&#xff1a;IntelliJ IDEA -> Preferences -> Plugins;Windows&#xff1a;File -> Settings -> Plugins.標注 1&#xff1a;顯示 IntelliJ IDEA 的插件分類&#xff0c; All plugins&#xff1a;顯示 IntelliJ …

杭漂兩年,深漂兩年,宇宙的盡頭到底在哪兒

hi&#xff0c;這里是桑小榆。這次分享的是一位杭漂兩年&#xff0c;深漂兩年的碼農伙伴的經歷。首先他能夠在大學期間就尋找到自己的熱愛并持之以恒值得令人學習。其次他的工作經歷可以說是非常的“程序員”&#xff0c;因為程序員所面對的職業生涯中&#xff0c;所謂的實習&a…

侶信即時通訊系統的技術解析

侶信&#xff1a; 說明&#xff1a; 侶信專業版是面向中小企業和者各類團隊組織內部交流使用工具,可以在互聯網或者局域網中使用。具有豐富的功能&#xff0c;聊天&#xff0c;群組&#xff0c;部門組織&#xff0c;內部朋友圈&#xff0c;以及漂流瓶搖一搖等功能。它可以在局域…

Confluence 6 使用 WebDAV 客戶端來對頁面進行操作

下面的部分告訴你如何在不同的系統中來設置原生的 WebDAV 客戶端&#xff0c;這個客戶端通常顯示在你操作系統的文件瀏覽器中&#xff0c;例如&#xff0c;Windows 的 Windows Explorer 或者 Linux 的 Konqueror。在 Mac OSX Finder 中訪問 Confluence你可以成功的連接&#xf…

.Net之接口小知識

目的通過一個簡單的項目&#xff0c;在原來的文章基礎上完善一下常用的幾種WebApi編寫方式以及請求方式&#xff0c;一方面是用于給我一個前端朋友用來學習調用接口&#xff0c;另一方面讓我測試HttpClient的一些效果。本文示例代碼環境&#xff1a;vs2022、net6準備新創建了一…

你所不知道的setTimeout

JavaScript提供定時執行代碼的功能&#xff0c;叫做定時器&#xff08;timer&#xff09;&#xff0c;主要由setTimeout()和setInterval()這兩個函數來完成。它們向任務隊列添加定時任務。初始接觸它的人都覺得好簡單&#xff0c;實時上真的如此么&#xff1f;這里記載下&#…

android 特效繪圖,Android繪圖機制與處理技巧——Android圖像處理之圖形特效處理...

Android變形矩陣——Matrix對于圖像的圖形變換&#xff0c;Android系統是通過矩陣來進行處理的&#xff0c;每個像素點都表達了其坐標的X、Y信息。Android的圖形變換矩陣是一個3x3的矩陣&#xff0c;如下圖所示&#xff1a;72F0CAC1-14FB-40F8-A430-8F542B09DC4E.png當使用變換…

WPF 使用 DrawingContext 繪制刻度條

WPF 使用 DrawingContext 繪制刻度條控件名&#xff1a;Ruler作者&#xff1a;WPFDevelopersOrg原文鏈接&#xff1a; https://github.com/WPFDevelopersOrg/WPFDevelopers框架使用大于等于.NET40&#xff1b;Visual Studio 2022;項目使用 MIT 開源許可協議&#xff1b;定義I…

純css實現漂亮又健壯的tooltip

前言 tooltip的實現有多種方式&#xff0c;下面是一個tooltip成長史。 預覽 https://codepen.io/moddx/pen/... 原始版 最簡單的莫過于就用原始title屬性&#xff0c;像這樣&#xff1a; <button title"tips">button</button> 缺點是體驗是差了點&#x…

個人中心的html,個人中心.html

&#xfeff;個人中心$axure.utils.getTransparentGifPath function() { return resources/images/transparent.gif; };$axure.utils.getOtherPath function() { return resources/Other.html; };$axure.utils.getReloadPath function() { return resources/reload.html; };…