若转载教程,请注明出自SW-X框架官方文档1

    1. <?php
    2. /**
    3. * 设计模式之备忘录模式
    4. * 使用场景:编辑器后退操作/数据库事物/存档
    5. * 小黄牛
    6. */
    7. header("Content-type: text/html; charset=utf-8");
    8. /**
    9. * 角色状态存储器
    10. */
    11. class RoleStateMemento{
    12. public $Life_Value; // 生命力
    13. /**
    14. * 构造方法存储角色状态
    15. */
    16. public function __construct($Life){
    17. $this->Life_Value = $Life;
    18. }
    19. }
    20. /**
    21. * 角色编辑器
    22. */
    23. class GameRole{
    24. public $LifeValue; // 生命力
    25. /**
    26. * 构造方法,初始化状态
    27. */
    28. function __construct(){
    29. $this->LifeValue = 100;
    30. }
    31. /**
    32. * 保存状态 - 将最新状态保存到状态存储器中
    33. */
    34. public function Save(){
    35. return (new RoleStateMemento(
    36. $this->LifeValue
    37. ));
    38. }
    39. /**
    40. * 恢复状态 - 从状态存储器中读取状态
    41. */
    42. public function Recovery($_memento){
    43. $this->LifeValue = $_memento->Life_Value;
    44. }
    45. /**
    46. * 被攻击
    47. */
    48. public function Display(){
    49. $this->LifeValue -= 10; // 每次被攻击减少10点生命值
    50. }
    51. /**
    52. * 打印生命值
    53. */
    54. public function Dump(){
    55. echo "当然角色状态:<br/>";
    56. if ($this->LifeValue <= 0) {
    57. echo "你已经挂了!<br/>";
    58. } else {
    59. echo "生命值:{$this->LifeValue}<br/>";
    60. }
    61. }
    62. }
    63. //游戏角色状态管理者类
    64. class RoleStateManager{
    65. public $Memento;
    66. }
    67. # 先创建一个角色
    68. $Role = new GameRole();
    69. # RPG游戏中经常出现,打BOSS前怕死先存档,肯定是玩家才有权力去存档
    70. $RoleMan = new RoleStateManager();
    71. $RoleMan->Memento = $Role->Save();
    72. # 开始打BOSS了
    73. $num = 1; // 记录回合数
    74. for ($i=0; $i<10; $i++){
    75. echo "-------------第{$num}回合------------<br/>";
    76. $Role->Display();
    77. $Role->Dump();
    78. $num++;
    79. # 在第5个回合的时候老妈杀来了,你经常会在战斗中存档一次,防止老妈拉电闸
    80. if($num == 6){
    81. $RoleMan2 = new RoleStateManager();
    82. $RoleMan2->Memento = $Role->Save();
    83. }
    84. }
    85. # 恢复存档:地狱模式打不过,还好他妈存档了!
    86. $Role->Recovery($RoleMan->Memento);
    87. $Role->Dump();
    88. # 咦,好像之前被老妈拉电闸有存档,恢复看下!
    89. $Role->Recovery($RoleMan2->Memento);
    90. $Role->Dump();

    浏览器输出

    1. -------------第1回合------------
    2. 当然角色状态:
    3. 生命值:90
    4. -------------第2回合------------
    5. 当然角色状态:
    6. 生命值:80
    7. -------------第3回合------------
    8. 当然角色状态:
    9. 生命值:70
    10. -------------第4回合------------
    11. 当然角色状态:
    12. 生命值:60
    13. -------------第5回合------------
    14. 当然角色状态:
    15. 生命值:50
    16. -------------第6回合------------
    17. 当然角色状态:
    18. 生命值:40
    19. -------------第7回合------------
    20. 当然角色状态:
    21. 生命值:30
    22. -------------第8回合------------
    23. 当然角色状态:
    24. 生命值:20
    25. -------------第9回合------------
    26. 当然角色状态:
    27. 生命值:10
    28. -------------第10回合------------
    29. 当然角色状态:
    30. 你已经挂了!
    31. 当然角色状态:
    32. 生命值:100
    33. 当然角色状态:
    34. 生命值:50

    备忘录模式

    1. 1.发起人(GameRole):负责创建一个备忘录,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。发起人可以根据需要决定备忘录存储自己的哪些内部状态。
    2. 2.备忘录(RoleStateSaveBox):负责存储发起人对象的内部状态,并可以防止发起人以外的其他对象访问备忘录。备忘录有两个接口:管理者只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。发起人却可看到备忘录的宽接口,允许它访问返回到先前状态所需要的所有数据。
    3. 3.管理者(GameRoleStateManager):负责存取备忘录,不能对的内容进行访问或者操作。

    优点

    1. 1、有时一些发起人对象的内部信息必须保存在发起人对象以外的地方,但是必须要由发起人对象自己读取,这时,使用备忘录模式可以把复杂的发起人内部信息对其他的对象屏蔽起来,从而可以恰当地保持封装的边界。
    2. 2、本模式简化了发起人类。发起人不再需要管理和保存其内部状态的一个个版本,客户端可以自行管理他们所需要的这些状态的版本。

    缺点

    1. 1、如果发起人角色的状态需要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象会很昂贵。
    2. 2、当负责人角色将一个备忘录存储起来的时候,负责人可能并不知道这个状态会占用多大的存储空间,从而无法提醒用户一个操作是否很昂贵。

    个人对这个模式的一些理解

    1. 这个模式在RPG游戏中经常会应用到,当你需要对当前游戏进度进行存档的时候, 你就会进入到 管理者的状态(管理者), 将当前游戏进度保存到存储器中(备忘录),至于编辑这个游戏的事情,就交由游戏本身来处理(发起人)。