【最佳实践】Go 状态模式

news/2025/3/18 19:41:38/

设计思路

状态模式的核心在于将对象的行为封装在特定的状态类中,使得对象在不同的状态下表现出不同的行为。每个状态实现同一个接口,允许对象在运行时通过改变其内部状态对象来改变其行为。状态模式使得状态转换更加明确,并且易于扩展新的状态和行为。

场景描述

假设我们有一个简单的文档编辑器,文档可以处于不同的编辑状态:草稿、审核、发布。每个状态对应不同的行为,比如在草稿状态下可以编辑内容,在审核状态下可以提交审核,在发布状态下可以查看内容但不能编辑。我们将使用状态模式来实现这一场景。

实现示例

下面是一个使用状态模式实现的 Go 语言示例,展示了一个简单的文档编辑系统:

package mainimport "fmt"// DocumentState 是状态接口,定义了文档状态的行为
type DocumentState interface {Edit() uiltin">errorSubmit() uiltin">errorPublish() uiltin">error
}// Document 是包含状态的上下文
type Document struct {state DocumentState
}// SetState 设置文档的当前状态
func (d *Document) SetState(state DocumentState) {d.state = state
}// Edit 触发编辑行为
func (d *Document) Edit() uiltin">error {return d.state.Edit()
}// Submit 触发提交审核行为
func (d *Document) Submit() uiltin">error {return d.state.Submit()
}// Publish 触发发布行为
func (d *Document) Publish() uiltin">error {return d.state.Publish()
}// DraftState 是草稿状态
type DraftState struct {document *Document
}func (s *DraftState) Edit() uiltin">error {fmt.Println("Editing the document.")return nil
}func (s *DraftState) Submit() uiltin">error {fmt.Println("Submitting the document for review.")s.document.SetState(&ReviewState{document: s.document})return nil
}func (s *DraftState) Publish() uiltin">error {return fmt.Errorf("document cannot be published directly from draft")
}// ReviewState 是审核状态
type ReviewState struct {document *Document
}func (s *ReviewState) Edit() uiltin">error {return fmt.Errorf("document cannot be edited during review")
}func (s *ReviewState) Submit() uiltin">error {return fmt.Errorf("document is already under review")
}func (s *ReviewState) Publish() uiltin">error {fmt.Println("Publishing the document.")s.document.SetState(&PublishedState{document: s.document})return nil
}// PublishedState 是已发布状态
type PublishedState struct {document *Document
}func (s *PublishedState) Edit() uiltin">error {return fmt.Errorf("document cannot be edited after publishing")
}func (s *PublishedState) Submit() uiltin">error {return fmt.Errorf("document is already published")
}func (s *PublishedState) Publish() uiltin">error {fmt.Println("Document is already published.")return nil
}func main() {// 创建一个文档,并设置初始状态为草稿document := &Document{}initialState := &DraftState{document: document}document.SetState(initialState)// 编辑文档err := document.Edit()if err != nil {fmt.Println("Error:", err)}// 提交文档审核err = document.Submit()if err != nil {fmt.Println("Error:", err)}// 尝试编辑文档(应失败,因为在审核中)err = document.Edit()if err != nil {fmt.Println("Error:", err)}// 发布文档err = document.Publish()if err != nil {fmt.Println("Error:", err)}// 尝试发布文档(应成功,因为已发布)err = document.Publish()if err != nil {fmt.Println("Error:", err)}
}

代码解释

  • DocumentState 接口:定义了文档状态的行为接口,包括 EditSubmitPublish 方法。每个状态实现这些行为。

  • Document 结构体:代表文档对象,包含一个 DocumentState。通过 SetState 方法可以改变文档的状态。

  • DraftState、ReviewState、PublishedState:分别实现了 DocumentState 接口,表示文档的不同状态。每个状态根据其特性实现了相应的行为。

  • main 函数:演示了如何使用状态模式管理文档的状态转换。文档初始状态为草稿,可以编辑和提交审核;审核状态下可以发布;发布状态下可以查看,但不能编辑或再次发布。

总结

状态模式」抽象过程的核心是:

  • 每一个状态映射对应行为
  • 行为实现同一个接口interface
  • 行为是内部的一个状态
  • 状态是不断变化的

http://www.ppmy.cn/news/1580142.html

相关文章

coding ability 展开第四幕(滑动指针——巩固篇)超详细!!!!

文章目录 前言水果成篮思路 找到字符串中所有字母异位词思路 串联所有单词的子串思路 最小覆盖子串思路 总结 前言 本专栏上一篇博客,带着大家从认识滑动窗口到慢慢熟悉 相信大家对滑动窗口已经有了大概的认识 其实主要就是抓住——一段连续的区间 今天来学习一些滑…

GaussDB备份数据常用命令

1、常用备份命令gs_dump 说明:是一个服务器端工具,可以在线导出数据库的数据,这些数据包含整个数据库或数据库中指定的对象(如:模式,表,视图等),并且支持导出完整一致的数…

物联网(IoT)平台层中 大数据处理过程

在物联网(IoT)平台层中,大数据处理是一个核心环节,它负责对海量设备数据进行采集、存储、处理和分析,以提取有价值的信息并支持上层应用。以下是物联网平台层中大数据处理的技术实现、架构设计和解决方案。 大数据处理的主要流程 物联网中的大数据处理通常包括以下几个阶…

LeetCode 1005. K 次取反后最大化的数组和 java题解

https://leetcode.cn/problems/maximize-sum-of-array-after-k-negations/description/ 看着简单但是写si人的一题。 class Solution {public int largestSumAfterKNegations(int[] nums, int k) {Arrays.sort(nums);//排序int last_negative-1,first_positive-1;//最后一个负…

单元测试、注解

目录 一、单元测试1.快速入门2.Junit在实际开发中的用法 二、注解1.注解概述2.自定义注解3.元注解4.解析注解 一、单元测试 单元测试就是针对最小的功能单元编写测试代码,Java程序最小的功能单元是方法。因此,单元测试就是针对Java方法的测试&#xff0…

泰山派开发之—Ubuntu24.04下Linux开发环境搭建

简介 最近翻到了吃灰已久的泰山派,是刚出来的时候用优惠券买的,当时价格挺便宜的,最近给它翻出来了,打算试试做个项目。买的泰山派容量是2G16G,SOC芯片使用的是RK3566,搭载1TOP算力的NPU,并且具…

【前端面试题】宏任务与微任务的区别

宏任务与微任务的区别 JavaScript采用单线程模型,通过 事件循环(Event Loop) 机制处理异步操作。 类比于厨师上菜的过程,顾客点的菜可能存在容易处理的 “软菜” 与难处理的 “硬菜” ,以及要加米饭酒水这些立马可以上…

【拓扑排序】火星词典

文章目录 LCR 114. 火星词典解题思路:拓扑排序 LCR 114. 火星词典 LCR 114. 火星词典 ​ 现有一种使用英语字母的外星文语言,这门语言的字母顺序与英语顺序不同。 ​ 给定一个字符串列表 words ,作为这门语言的词典,words 中的…