首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >go: Memento Pattern

go: Memento Pattern

作者头像
geovindu
发布2026-06-18 18:21:15
发布2026-06-18 18:21:15
560
举报

项目结构:

代码语言:javascript
复制
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Memento Pattern备忘录模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/4/26 15:22
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : memento.go
*/
package entity
 
// Memento 备忘录顶层接口
// 企业级规范:面向接口编程,方便扩展不同类型备忘录
type Memento interface {
    GetID() string // 唯一标识
}
 
// ==============================================
// 以下为私有实现:外部包无法访问,保证封装性
// ==============================================
 
// bizMemento 业务备忘录(私有结构体,外部无法读写状态)
type bizMemento struct {
    id        string // 快照ID
    stateData []byte // 序列化后的原发器状态(二进制,绝对安全)
}
 
func (m *bizMemento) GetID() string {
    return m.id
}
 
// NewBizMemento 创建备忘录(仅内部包可调用)
func NewBizMemento(id string, state []byte) Memento {
    return &bizMemento{id: id, stateData: state}
}
 
// GetState 获取状态(仅内部包可调用)
func (m *bizMemento) GetState() []byte {
    return m.stateData
}
 
 
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Memento Pattern备忘录模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/4/26 15:23
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : originator.go
*/
package entity
 
import "encoding/json"
 
// Originator 原发器接口
// 所有需要备份/回退的对象都必须实现该接口
type Originator interface {
    CreateMemento(id string) (Memento, error) // 创建快照
    RestoreFromMemento(m Memento) error       // 从快照恢复
}
 
// ==============================================
// 业务原发器示例:企业配置(可替换为订单/设备/商品)
// ==============================================
 
// EnterpriseConfig 企业配置(真实业务可替换为任意实体)
type EnterpriseConfig struct {
    CompanyID string  `json:"company_id"` // 企业ID
    Name      string  `json:"name"`       // 企业名称
    Version   int     `json:"version"`    // 配置版本
    Status    string  `json:"status"`     // 状态:enable/disable
    Balance   float64 `json:"balance"`    // 账户余额
}
 
// CreateMemento 创建备忘录:序列化状态为二进制(安全封装)
func (e *EnterpriseConfig) CreateMemento(id string) (Memento, error) {
    // 序列化为JSON二进制(可替换为Protobuf/gob)
    stateBytes, err := json.Marshal(e)
    if err != nil {
        return nil, err
    }
    return NewBizMemento(id, stateBytes), nil
}
 
// RestoreFromMemento 从备忘录恢复状态
func (e *EnterpriseConfig) RestoreFromMemento(m Memento) error {
    bizM := m.(*bizMemento)
    // 反序列化
    return json.Unmarshal(bizM.GetState(), e)
}
 
// 业务方法:修改状态
func (e *EnterpriseConfig) UpdateBalance(balance float64) {
    e.Balance = balance
    e.Version++
}
 
func (e *EnterpriseConfig) UpdateStatus(status string) {
    e.Status = status
    e.Version++
}
代码语言:javascript
复制
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Memento Pattern备忘录模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/4/26 15:23
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : memento_store.go
*/
package repository
 
import (
    "errors"
    "godesginpattern/memento/entity"
)
 
// MementoStore 备忘录存储接口
// 支持扩展:内存存储、Redis存储、MySQL存储
type MementoStore interface {
    Save(m entity.Memento) error           // 保存备忘录
    Get(id string) (entity.Memento, error) // 获取备忘录
    List() []entity.Memento                // 获取所有快照
}
 
// ==============================================
// 默认实现:内存存储(生产可替换)
// ==============================================
 
type memoryStore struct {
    mementos map[string]entity.Memento
}
 
func NewMemoryStore() MementoStore {
    return &memoryStore{
        mementos: make(map[string]entity.Memento),
    }
}
 
func (m *memoryStore) Save(me entity.Memento) error {
    m.mementos[me.GetID()] = me
    return nil
}
 
func (m *memoryStore) Get(id string) (entity.Memento, error) {
    me, ok := m.mementos[id]
    if !ok {
        return nil, errors.New("备忘录不存在")
    }
    return me, nil
}
 
func (m *memoryStore) List() []entity.Memento {
    list := make([]entity.Memento, 0, len(m.mementos))
    for _, v := range m.mementos {
        list = append(list, v)
    }
    return list
}
代码语言:javascript
复制
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Memento Pattern备忘录模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/4/26 15:23
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : memento_service'.go
*/
package service
 
import (
    "godesginpattern/memento/entity"
    "godesginpattern/memento/repository"
)
 
// MementoService 备忘录服务(Caretaker 负责人)
// 职责:只管理备忘录的保存、获取、回滚,不修改任何业务数据
type MementoService struct {
    store repository.MementoStore
}
 
func NewMementoService(store repository.MementoStore) *MementoService {
    return &MementoService{store: store}
}
 
// Backup 备份原发器状态
func (s *MementoService) Backup(originator entity.Originator, snapshotID string) error {
    m, err := originator.CreateMemento(snapshotID)
    if err != nil {
        return err
    }
    return s.store.Save(m)
}
 
// Rollback 回滚到指定快照
func (s *MementoService) Rollback(originator entity.Originator, snapshotID string) error {
    m, err := s.store.Get(snapshotID)
    if err != nil {
        return err
    }
    return originator.RestoreFromMemento(m)
}
 
// ListSnapshots 获取所有备份列表
func (s *MementoService) ListSnapshots() []entity.Memento {
    return s.store.List()
}

调用:

代码语言:javascript
复制
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Memento Pattern备忘录模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/4/26 18:54
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : mementobll.go
memento/
├── go.mod                  # 项目模块
├── internal/               # 内部包(外部不可访问)
│   ├── entity/             # 实体层:原发器、备忘录(核心数据)
│   │   ├── memento.go      # 备忘录接口 + 实现
│   │   └── originator.go   # 原发器接口 + 业务实体
│   ├── repository/         # 存储层:备忘录持久化/存储
│   │   └── memento_store.go
│   └── service/            # 服务层:负责人(Caretaker)核心逻辑
│       └── memento_service.go
└── cmd/                    # 应用层:入口、测试用例
 
    └── main.go
*/
package bll
 
import (
    "fmt"
    "godesginpattern/memento/entity"
    "godesginpattern/memento/repository"
    "godesginpattern/memento/service"
)
 
func MementoMain() {
    // ===================== 1. 初始化依赖(DI依赖注入) =====================
    store := repository.NewMemoryStore()        // 存储层
    memoSvc := service.NewMementoService(store) // 服务层
 
    // ===================== 2. 创建原发器(企业配置) =====================
    config := &entity.EnterpriseConfig{
        CompanyID: "COMPANY_001",
        Name:      "科技有限公司",
        Version:   1,
        Status:    "enable",
        Balance:   100000.00,
    }
 
    fmt.Println("===== 初始状态 =====")
    printConfig(config)
 
    // ===================== 3. 备份 V1 版本 =====================
    _ = memoSvc.Backup(config, "SNAPSHOT_V1")
    fmt.Println("\n✅ 已备份 SNAPSHOT_V1")
 
    // ===================== 4. 修改状态 =====================
    config.UpdateBalance(80000.00)
    config.UpdateStatus("disable")
 
    fmt.Println("\n===== 修改后状态 V2 =====")
    printConfig(config)
 
    // ===================== 5. 备份 V2 版本 =====================
    _ = memoSvc.Backup(config, "SNAPSHOT_V2")
    fmt.Println("\n✅ 已备份 SNAPSHOT_V2")
 
    // ===================== 6. 再次修改 =====================
    config.UpdateBalance(50000.00)
    fmt.Println("\n===== 二次修改状态 =====")
    printConfig(config)
 
    // ===================== 7. 回滚到 V1 =====================
    fmt.Println("\n🔄 回滚到 SNAPSHOT_V1")
    _ = memoSvc.Rollback(config, "SNAPSHOT_V1")
    printConfig(config)
 
    // ===================== 8. 回滚到 V2 =====================
    fmt.Println("\n🔄 回滚到 SNAPSHOT_V2")
    _ = memoSvc.Rollback(config, "SNAPSHOT_V2")
    printConfig(config)
}
 
// printConfig 打印配置状态
func printConfig(c *entity.EnterpriseConfig) {
    fmt.Printf("企业ID:%s\n名称:%s\n版本:%d\n状态:%s\n余额:%.2f\n",
        c.CompanyID, c.Name, c.Version, c.Status, c.Balance)
}

输出:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2026-06-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档