《golang设计模式》第三部分·行为型模式-06-备忘录模式(Memento)

文章目录

  • [1. 概述](#1. 概述)
    • [1.1 角色](#1.1 角色)
    • [1.2 类图](#1.2 类图)
  • [2. 代码示例](#2. 代码示例)
    • [2.1 设计](#2.1 设计)
    • [2.2 代码](#2.2 代码)
    • [2.3 类图](#2.3 类图)

1. 概述

备忘录(Memento)用于在不破坏目标对象封装特性的基础上,将目标对象内部的状态存储到外部对象中,以备之后恢复状态时使用。

1.1 角色

  • Originator(发起者):当前的基础对象,它会将自己的状态保存进备忘录。
    • savememento()方法:Originator通过该方法将它自己状态保存进一个备忘录对象。
    • restorememento()方法:Originator通过该方法将它自己状态回滚至指定备忘录。
  • Memento(备忘录) : 存储Originator状态的对象
  • Caretaker(管理者):保存多条备忘录的对象,并维护着备忘录的索引,在需要的时候会返回相应的备忘录。

1.2 类图

Originator -state:State +RestoreState(m:Memento) +CreateMemento() Memento -state:State +GetState() Caretaker +StoreMemento(m:Memento) +GetMemento(c:Condition)

2. 代码示例

2.1 设计

  • 定义备忘录memento来记录发起者状态
  • 它的Get()方法获取它的状态
  • 定义发起者Originator
    • 它的方法 CreateMemento() 用它自己创建一条备忘录
    • 它的方法 RollBack() 将它自己回滚至指定备忘录的状态
    • 它的Set()方法可以设置它的状态
    • 它的Get()方法可以获取它的状态
  • 创建一个管理者Caretaker,它是备忘录Memento的聚合
    • 它的AddMemento方法,向它自身加入一条备忘录
    • 它的GetMemento()方法,查询一条它管理的指定备忘录
  • 调用
    • 初始化
      • 实例化一个管理者caretaker
      • 实例化一个发起者originator
    • 创建备忘录测试
      • 第一次
        • 用发起者创建一条备忘录
        • 管理者收录该备忘录
      • 第二次
        • 改变发起者状态
        • 用发起者创建一条新备忘录
        • 管理者收录该备忘录
      • 第三次
        • 改变发起者状态
        • 用发起者创建一条新备忘录
        • 管理者收录该备忘录
      • 查看管理者信息,应该有三条备忘录
    • 回滚测试
      • 从管理者获取指定索引的备忘录
      • 将发起者回滚至该备忘录状态

2.2 代码

  • 代码
go 复制代码
package main

import "fmt"

// 定义备忘录
type Memento struct {
	state string
}

// 查备忘录状态
func (m *Memento) Get() string {
	return m.state
}

// 定义发起者
type Originator struct {
	state string
}

// 根据发起者状态创建一条备忘录
func (e *Originator) CreateMemento() (memento *Memento) {
	memento = &Memento{state: e.state}
	fmt.Printf("创建一条备忘录:%+v\n", memento)
	return memento
}

// 将发起者状态回滚至指定备忘录状态
func (e *Originator) RollBack(m *Memento) {
	e.state = m.Get()
	fmt.Printf("发起者状态回滚至:%v\n", e)
}

// 设置发起者状态
func (e *Originator) Set(state string) {
	e.state = state
	fmt.Println("发起者状态更改为:", e.state)
}

// 获取发起者状态
func (e *Originator) Get() string {
	fmt.Println("获取发起者状态为:", e.state)
	return e.state
}

// 定义管理者,管理者是备忘录的聚合
type Caretaker struct {
	mementoArray []*Memento
}

// 向管理者中添加一条备忘录
func (c *Caretaker) AddMemento(m *Memento) {
	fmt.Printf("向管理者中添加一条备忘录:%+v\n", m)
	c.mementoArray = append(c.mementoArray, m)
}

// 获取指定备忘录信息
func (c *Caretaker) GetMemento(index int) *Memento {
	fmt.Printf("获取到第 %d 条备忘录信息为:%+v\n", index, c.mementoArray[index])
	return c.mementoArray[index]
}

func main() {
	//实例化一个管理者
	caretaker := &Caretaker{
		mementoArray: make([]*Memento, 0),
	}
	//实例化一个发起者
	originator := &Originator{
		state: "A",
	}

	//为发起者创建一条备忘录
	memento0 := originator.CreateMemento()
	//在管理者中加入该备忘录
	caretaker.AddMemento(memento0)

	//改变发起者状态
	originator.Set("B")
	//为发起者创建第二条备忘录
	memento1 := originator.CreateMemento()
	//在管理者中加入该备忘录
	caretaker.AddMemento(memento1)

	//再次改变发起者状态
	originator.Set("C")
	//为发起者创建第三条备忘录
	memento2 := originator.CreateMemento()
	//在管理者中加入该备忘录
	caretaker.AddMemento(memento2)
	fmt.Println("此时管理者应该有三条备忘录:")
	for _, memento := range caretaker.mementoArray {
		fmt.Printf("%+v\n", memento)
	}
	
	fmt.Println("=========回滚测试===========")
	originator.RollBack(caretaker.GetMemento(1))
	fmt.Println("=========回滚测试===========")
	originator.RollBack(caretaker.GetMemento(0))
}
  • 输出
shell 复制代码
创建一条备忘录:&{state:A}
向管理者中添加一条备忘录:&{state:A} 
发起者状态更改为: B
创建一条备忘录:&{state:B}
向管理者中添加一条备忘录:&{state:B} 
发起者状态更改为: C
创建一条备忘录:&{state:C}
向管理者中添加一条备忘录:&{state:C} 
此时管理者应该有三条备忘录
&{state:A}
&{state:B}
&{state:C}
=========回滚测试===========
获取到第 1 条备忘录信息为:&{state:B}
发起者状态回滚至:&{B}
=========回滚测试===========
获取到第 0 条备忘录信息为:&{state:A}
发起者状态回滚至:&{A}

2.3 类图

Originator -string:State +CreateMemento() +RollBack(m *Memento) +Set(state string) +Get() Memento -String:State +Get() Caretaker +[]*Memento:mementoArray +AddMemento(m *Memento) +GetMemento(index int) : Memento


相关推荐
U盘失踪了1 天前
Go 结构体
笔记·golang
wuyikeer1 天前
Spring Boot 经典九设计模式全览
java·spring boot·设计模式
贺小涛1 天前
python和golang进程、线程、协程区别
java·python·golang
迷茫运维路1 天前
云枢运维管理系统
运维·golang·kubernetes·gin·casbin
Old Uncle Tom1 天前
Agent 技能的五种设计模式
设计模式
jieyucx1 天前
Go 语言运算符与控制台输入输出详解
开发语言·后端·golang
祁_z1 天前
【ReACT 设计模式】(思考 - 行动 - 观察)
设计模式
Makoto_Kimur1 天前
Spring用了哪些设计模式?
java·spring·设计模式
sg_knight1 天前
设计模式实战:中介者模式(Mediator)
microsoft·设计模式·中介者模式
userxxcc1 天前
Waigo是用“Golang+Web”写的“视图窗口+稳定服务”的桌面端(Win、Mac、Ubuntu)多功能程序基座。开箱即用但有一定上手门槛。
javascript·golang·桌面应用基座·wails3