zoukankan      html  css  js  c++  java
  • 备忘录模式(17)

    今天,我们来讲备忘录模式

    一、案例:

    小伙伴们都玩过单机游戏或者说RPG类的游戏吧,我们在打BOSS之前,需要先存一下档,以免BOSS打不过从头再来,好,下面,我们用简单的控制台应用程序来描述一下这个场景。

     1     /// <summary>
     2     /// 游戏角色类
     3     /// </summary>
     4     class GameRole
     5     {
     6         //生命值
     7         private int vit;
     8 
     9         public int Vit
    10         {
    11             get
    12             {
    13                 return vit;
    14             }
    15 
    16             set
    17             {
    18                 vit = value;
    19             }
    20         }
    21         //攻击力
    22         private int atk;
    23         public int Def
    24         {
    25             get
    26             {
    27                 return def;
    28             }
    29 
    30             set
    31             {
    32                 def = value;
    33             }
    34         }
    35         private int def;
    36         //防御力
    37         public int Atk
    38         {
    39             get
    40             {
    41                 return atk;
    42             }
    43 
    44             set
    45             {
    46                 atk = value;
    47             }
    48         }
    49         //状态显示
    50         public void StateDisplay()
    51         {
    52             Console.WriteLine("角色当前状态:");
    53             Console.WriteLine($"体力:{this.vit}");
    54             Console.WriteLine($"攻击力:{this.atk}");
    55             Console.WriteLine($"防御力:{this.def}");
    56             Console.WriteLine("");
    57         }
    58         /// <summary>
    59         /// 获取初始状态
    60         /// 数据通常来自本机磁盘或远程数据库
    61         /// </summary>
    62         public void GetInitState()
    63         {
    64             this.vit = 100;
    65             this.atk = 100;
    66             this.def = 100;
    67         }
    68         /// <summary>
    69         /// 战斗
    70         /// 在与Boss大战后游戏数据损耗为0
    71         /// </summary>
    72         public void Fight()
    73         {
    74             this.vit = 0;
    75             this.atk = 0;
    76             this.def = 0;
    77         }
    78     }

    客户端调用:

     1         public static void Main()
     2         {
     3             //大战Boss前
     4             GameRole lixiaoyao = new GameRole();
     5             //大战Boss前,获得初始角色状态
     6             lixiaoyao.GetInitState();
     7             lixiaoyao.StateDisplay();
     8 
     9             //保存进度,通过‘游戏角色’的新实例来保存进度
    10             GameRole backup = new GameRole();
    11             backup.Vit = lixiaoyao.Vit;
    12             backup.Atk = lixiaoyao.Atk;
    13             backup.Def = lixiaoyao.Def;
    14             
    15             //大战Boss 损耗很严重
    16             lixiaoyao.Fight();
    17             lixiaoyao.StateDisplay();
    18 
    19             //恢复之前状态
    20             lixiaoyao.Vit = backup.Vit;
    21             lixiaoyao.Atk = backup.Atk;
    22             lixiaoyao.Def = backup.Def;
    23             lixiaoyao.StateDisplay();
    24             Console.ReadKey();
    25         }

    好了,我们很好的描述了我们案例中的场景,那下面,我们看一下我们这段代码有什么不足吗?请看

      //保存进度,通过‘游戏角色’的新实例来保存进度
                GameRole backup = new GameRole();
                backup.Vit = lixiaoyao.Vit;
                backup.Atk = lixiaoyao.Atk;
                backup.Def = lixiaoyao.Def;
       //恢复之前状态
                lixiaoyao.Vit = backup.Vit;
                lixiaoyao.Atk = backup.Atk;
                lixiaoyao.Def = backup.Def;
                lixiaoyao.StateDisplay();

    这两段代码在客户端暴露了细节,客户端的责任太多了,要知道角色的状态,还要备份,如果今后需要对角色增加 魔力值 这个属性,那都是非常麻烦的事情了。

    显然,我们希望将角色的存取状态细节封存起来,最好是封装在外部的类当中,以体现职责分离。

    面对上述的要求,这里,我们就需要学习一种新的设计模式了,备忘录模式。

    备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样就可以将对象恢复到原先保存的那个状态。

    好,下面我们来看一下设计模式的基本结构代码,需要三个类

     1     /// <summary>
     2     /// 发起人类
     3     /// </summary>
     4     class Originator
     5     {
     6         /// <summary>
     7         /// 需要保存的属性,可以是多个
     8         /// </summary>
     9         private string state;
    10 
    11         public string State
    12         {
    13             get
    14             {
    15                 return state;
    16             }
    17 
    18             set
    19             {
    20                 state = value;
    21             }
    22         }
    23         /// <summary>
    24         /// 创建备忘录,将当前需要保存的信息导入并实例化出一个Memento对象
    25         /// </summary>
    26         /// <returns></returns>
    27         public Memento CraeteMemento()
    28         {
    29             return new Memento(state);
    30         }
    31 
    32         public void SetMemento(Memento memento)
    33         {
    34             state = memento.State;
    35         }
    36         /// <summary>
    37         /// 显示数据
    38         /// </summary>
    39         public void Show()
    40         {
    41             Console.WriteLine($"State={state}");
    42         }
    43     }
    44     /// <summary>
    45     /// 备忘录类
    46     /// </summary>
    47     class Memento
    48     {
    49         private string state;
    50         /// <summary>
    51         /// 构造方法,将相关数据导入
    52         /// </summary>
    53         /// <param name="state"></param>
    54         public Memento(string state)
    55         {
    56             this.state = state;
    57         }
    58         /// <summary>
    59         /// 需要保存的数据属性,可以是多个
    60         /// </summary>
    61         public string State
    62         {
    63             get { return state; }
    64         }
    65     }
    66     /// <summary>
    67     /// 管理者
    68     /// </summary>
    69     class Caretaker
    70     {
    71         /// <summary>
    72         /// 属性,得到或设置备忘录
    73         /// </summary>
    74         private Memento memento;
    75 
    76         internal Memento Memento
    77         {
    78             get
    79             {
    80                 return memento;
    81             }
    82 
    83             set
    84             {
    85                 memento = value;
    86             }
    87         }
    88     }

    客户端调用:

     1         public static void Main()
     2         {
     3             //Originator 初始状态,状态属性为”On“
     4             Originator o = new Originator();
     5             o.State = "On";
     6             o.Show();
     7 
     8             //保存状态时,由于有了很好的封装,可以隐藏Originator的实现细节
     9             Caretaker c = new Caretaker();
    10             c.Memento = o.CraeteMemento();
    11 
    12             //改变Originator状态为”Off“
    13             o.State = "Off";
    14             o.Show();
    15 
    16             //恢复原始状态
    17             o.SetMemento(c.Memento);
    18             o.Show();
    19             Console.ReadKey();
    20         }

    好,我们就用备忘录模式来写一下我们案例中的代码

      1     /// <summary>
      2     /// 游戏角色类(发起者)
      3     /// </summary>
      4     class GameRole
      5     {
      6         //生命值
      7         private int vit;
      8 
      9         public int Vit
     10         {
     11             get
     12             {
     13                 return vit;
     14             }
     15 
     16             set
     17             {
     18                 vit = value;
     19             }
     20         }
     21         //攻击力
     22         private int atk;
     23         public int Def
     24         {
     25             get
     26             {
     27                 return def;
     28             }
     29 
     30             set
     31             {
     32                 def = value;
     33             }
     34         }
     35         private int def;
     36         //防御力
     37         public int Atk
     38         {
     39             get
     40             {
     41                 return atk;
     42             }
     43 
     44             set
     45             {
     46                 atk = value;
     47             }
     48         }
     49         //状态显示
     50         public void StateDisplay()
     51         {
     52             Console.WriteLine("角色当前状态:");
     53             Console.WriteLine($"体力:{this.vit}");
     54             Console.WriteLine($"攻击力:{this.atk}");
     55             Console.WriteLine($"防御力:{this.def}");
     56             Console.WriteLine("");
     57         }
     58         /// <summary>
     59         /// 获取初始状态
     60         /// 数据通常来自本机磁盘或远程数据库
     61         /// </summary>
     62         public void GetInitState()
     63         {
     64             this.vit = 100;
     65             this.atk = 100;
     66             this.def = 100;
     67         }
     68         /// <summary>
     69         /// 战斗
     70         /// 在与Boss大战后游戏数据损耗为0
     71         /// </summary>
     72         public void Fight()
     73         {
     74             this.vit = 0;
     75             this.atk = 0;
     76             this.def = 0;
     77         }
     78         /// <summary>
     79         /// 保存角色状态
     80         /// </summary>
     81         /// <returns></returns>
     82         public RoleStateMemtento SaveState()
     83         {
     84             return new RoleStateMemtento(vit, atk, def);
     85         }
     86         /// <summary>
     87         /// 恢复角色状态
     88         /// </summary>
     89         /// <param name="memento"></param>
     90         public void RecoverState(RoleStateMemtento memento)
     91         {
     92             this.vit = memento.Vit;
     93             this.atk = memento.Atk;
     94             this.def = memento.Def;
     95         }
     96     }
     97     /// <summary>
     98     /// 角色状态储存箱(备忘录)
     99     /// </summary>
    100     class RoleStateMemtento
    101     {
    102         private int vit;
    103         private int atk;
    104         private int def;
    105 
    106         public int Vit
    107         {
    108             get
    109             {
    110                 return vit;
    111             }
    112 
    113             set
    114             {
    115                 vit = value;
    116             }
    117         }
    118 
    119         public int Atk
    120         {
    121             get
    122             {
    123                 return atk;
    124             }
    125 
    126             set
    127             {
    128                 atk = value;
    129             }
    130         }
    131 
    132         public int Def
    133         {
    134             get
    135             {
    136                 return def;
    137             }
    138 
    139             set
    140             {
    141                 def = value;
    142             }
    143         }
    144         /// <summary>
    145         /// 将生命力,攻击力,防御力 存入状态存储箱对象中
    146         /// </summary>
    147         /// <param name="vit"></param>
    148         /// <param name="atk"></param>
    149         /// <param name="def"></param>
    150         public RoleStateMemtento(int vit, int atk, int def)
    151         {
    152             this.vit = vit;
    153             this.atk = atk;
    154             this.def = def;
    155         }
    156     }
    157     /// <summary>
    158     /// 管理者
    159     /// </summary>
    160     class RoleStateCaretaker
    161     {
    162         private RoleStateMemtento memento;
    163 
    164         internal RoleStateMemtento Memento
    165         {
    166             get
    167             {
    168                 return memento;
    169             }
    170 
    171             set
    172             {
    173                 memento = value;
    174             }
    175         }
    176     }

    客户端调用:

     1         public static void Main()
     2         {
     3             //大战Boss前
     4             //游戏角色初始状态,三项指标都为100
     5             GameRole lixiaoyao = new GameRole();
     6             lixiaoyao.GetInitState();
     7             lixiaoyao.StateDisplay();
     8 
     9             //保存进度
    10             //保存进度时,由于封装在Memento中,因此,我们并不知道保存了哪些具体的角色数据
    11             RoleStateCaretaker stateAdmin = new RoleStateCaretaker();
    12             stateAdmin.Memento = lixiaoyao.SaveState();
    13 
    14             //大战Boss,损耗严重
    15             //三项指标都为0,GameOver了。
    16             lixiaoyao.Fight();
    17             lixiaoyao.StateDisplay();
    18 
    19             //恢复之前状态
    20             lixiaoyao.RecoverState(stateAdmin.Memento);
    21             lixiaoyao.StateDisplay();
    22             Console.ReadKey();
    23         }

    好了,今天备忘录模式就讲到这里,下一篇博文,我们讲 组合模式


    本系列将持续更新,喜欢的小伙伴可以点一下关注和推荐,谢谢大家的支持

  • 相关阅读:
    [LA] 3027
    [POJ] 3264 Balanced Lineup [ST算法]
    [LA] 3644
    [Codeforces Round #248 (Div. 2)] B. Kuriyama Mirai's Stones
    [Codeforces Round #248 (Div. 2)] A. Kitahara Haruki's Gift
    [Codeforces Round #247 (Div. 2)] B. Shower Line
    [Codeforces Round #247 (Div. 2)] A. Black Square
    [UVA] 784
    [OpenJudge] 百练2754 八皇后
    449 Set、Map数据结构
  • 原文地址:https://www.cnblogs.com/xiaomowang/p/6372887.html
Copyright © 2011-2022 走看看