跟着老侯玩编程 跟着老侯玩编程
首页
  • 基础语法
  • 网络编程
  • 设计模式
  • 基础篇
  • 进阶篇
  • 框架篇
  • Redis
  • Alibaba
  • 课程目录
  • 码农宝典
留言
首页
  • 基础语法
  • 网络编程
  • 设计模式
  • 基础篇
  • 进阶篇
  • 框架篇
  • Redis
  • Alibaba
  • 课程目录
  • 码农宝典
留言
  • 基础语法

    • 单元文件
    • 变量和常量
    • 内联变量
    • 基本数据类型
    • 复合数据类型
    • 语句(选择语句)
    • 语句(循环语句)
    • 数组
    • 初识例程
    • 初识面向对象
    • 属性Property
    • 面向对象的方法
    • 指针
    • 接口
    • 匿名函数和委托实现
    • 多态
    • 字符串详解
    • 异常处理
    • 反射机制
    • 泛型容器
    • JSON
    • 文件操作
    • Dll创建并调用
    • DLL初始化和退出处理
    • Package
    • 理解消息循环
    • VCL与Windows消息
    • 钩子原理
    • 进程通讯-内存映像
    • 多线程开篇
    • 线程控制
    • 线程同步
  • 网络编程

    • 网络编程基础
    • Delphi网络编程
    • select
    • WSAAsyncSelect
    • WSAEventSelect
  • 设计模式

    • 单例模式
    • 单例模式二
    • 策略模式
    • 简单工厂模式
    • 建造者模式
    • 原型模式
    • 模板方法模式
    • 状态模式
    • 迭代器模式
    • 解释器模式
    • 责任链模式
    • 中介者模式
    • 备忘录模式
      • 优缺点
      • 案例代码
    • 命令模式
    • 观察者模式
    • 访问者模式
    • 适配器模式
    • 桥接模式
  • Delphi
  • 设计模式
舞动的代码
2022-04-29
目录

备忘录模式

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

这种模式的应用比较常见,例如游戏存档、撤销、浏览器中的后退和数据库中的事务管理等等。其核心类图如下

  • Originator:源发器类,负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态

  • Memento:备忘录类,负责存储Originator对象的内部状态,并可防止Originator以外的其他对象访问备忘录Memento

  • Caretaker:备忘录类的管理者,负责保存好备忘录的Memento

# 优缺点

优点是给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。同时实现了信息的封装,使得用户不需要关心状态的保存细节。

缺点是消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。

# 案例代码

以游戏存档为例,看一下如何用备忘录模式实现。案例来自网络,博客的代码貌似是Java,但是并不妨碍

博客地址:https://www.cnblogs.com/adamjwh/p/11018268.html


program Memento;

{$APPTYPE CONSOLE}
{$R *.res}

uses
    System.SysUtils;

type
    // 类型前置声明
    TRole = class;

    // 备忘录类
    TRoleMemento = class
    private
        // 生命力
        FVitality: Integer;
        // 攻击力
        FAggressivity: Integer;
        // 防御力
        FDefensivePower: Integer;

    public
        property Vitality: Integer read FVitality write FVitality;

        property Aggressivity: Integer read FAggressivity write FAggressivity;

        property DefensivePower: Integer read FDefensivePower write FDefensivePower;
        // 重写构造
        constructor Create(Role: TRole); overload;
    end;

    // 备忘录管理者类
    TRoleStateCaretaker = class
    private
        // 这里为了降低学习成本仅仅保存了备忘录中的一个节点,如果需要可以使用容器对象
        FRoleMemento: TRoleMemento;

    public
        property RoleMemento: TRoleMemento read FRoleMemento write FRoleMemento;
    end;

    // 游戏的角色类即源发器类
    TRole = class
    private
        // 生命力
        FVitality: Integer;
        // 攻击力
        FAggressivity: Integer;
        // 防御力
        FDefensivePower: Integer;

    public
        property Vitality: Integer read FVitality write FVitality;

        property Aggressivity: Integer read FAggressivity write FAggressivity;

        property DefensivePower: Integer read FDefensivePower write FDefensivePower;

        // 存档

        function RoleMemento(): TRoleMemento;

        // 恢复
        procedure RoleRecovery(RoleMemento: TRoleMemento);
    end;

    { TRole }

function TRole.RoleMemento: TRoleMemento;
begin
    Result := TRoleMemento.Create(Self);
end;

procedure TRole.RoleRecovery(RoleMemento: TRoleMemento);
begin
    Self.Vitality := RoleMemento.Vitality;
    Self.Aggressivity := RoleMemento.Aggressivity;
    Self.DefensivePower := RoleMemento.DefensivePower;
end;

{ TRoleMemento }

constructor TRoleMemento.Create(Role: TRole);
begin
    Self.Vitality := Role.Vitality;
    Self.Aggressivity := Role.Aggressivity;
    Self.DefensivePower := Role.DefensivePower;
end;

// 测试代码
begin
    try
        var
        Role := TRole.Create;
        // 初始化角色的状态信息
        Role.Vitality := 10;
        Role.Aggressivity := 2;
        Role.DefensivePower := 4;
        Writeln('角色初始状态:生命力:', Role.Vitality, ',攻击力:', Role.Aggressivity, ',防御力:', Role.DefensivePower);
        // 存档
        var
        RoleStateCaretaker := TRoleStateCaretaker.Create();
        RoleStateCaretaker.RoleMemento := Role.RoleMemento;

        // 变更角色状态信息
        Role.Vitality := 5;
        Role.Aggressivity := 1;
        Role.DefensivePower := 2;
        Writeln('角色打怪之后状态:生命力:', Role.Vitality, ',攻击力:', Role.Aggressivity, ',防御力:', Role.DefensivePower);

        // 打坐或者嗑药之后恢复状态
        Role.RoleRecovery(RoleStateCaretaker.RoleMemento);
        Writeln('角色恢复之后状态:生命力:', Role.Vitality, ',攻击力:', Role.Aggressivity, ',防御力:', Role.DefensivePower);

        Readln;
    except
        on E: Exception do Writeln(E.ClassName, ': ', E.Message);
    end;

end.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
中介者模式
命令模式

← 中介者模式 命令模式→

Theme by Vdoing | Copyright © 2013-2023 冀ICP备16006233号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×