设计模式学习-使用go实现状态模式
状态模式
定义
状态模式(state):当一个条件的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是当控制一个对象状态转换的的条件表达式过于复杂,把状态的判断逻辑转移到表示不同状态的一些列类当中,可以把复杂的判断逻辑简化。
如果状态判断很简单,就没必要使用状态模式了。
状态机
状态机有3个组成部分:状态(State)、事件(Event)、动作(Action)。
状态机的实现方式有三种:
1、分支逻辑法;
就是参照状态转移图,将每一个状态转移,原模原样地直译成代码。这样编写的代码会包含大量的if-else或switch-case分支判断逻辑,甚至是嵌套的分支判断逻辑。
2、查表法;
就是把对应的状态,以及状态对应的时间放入到数据或者 map 中,这样通过根据业务的状态,查询数据或者 map 就能找到对应需要执行的事件。
对于状态很多、状态转移比较复杂的状态机来说,查表法比较合适。通过二维数组来表示状态转移图,能极大地提高代码的可读性和可维护性。
3、状态模式。
如果状态对应的执行操作很复杂,需要一些列的复杂的逻辑操作,这时候就需要引入状态模式了。
优点
1、将与特定状态相关的代码放在单独的类中;
2、无需修改已有状态类和上下文就能引入新状态;
3、通过消除臃肿的状态机条件语句简化上下文代码。
缺点
1、状态模式的使用必然会增加系统类和对象的个数;
2、如果状态机只有几个状态,或者很少发生改变,使用状态模式反而会使系统变的复杂。
适用范围
1、如果对象需要根据自身当前状态进行不同行为,同时状态的数量非常多且与状态相关的代码会频繁变更的话,可使用状态模式;
2、如果某个类需要根据成员变量的当前值改变自身行为,从而需要使用大量的条件语句时,可使用该模式;
3、当相似状态和基于条件的状态机转换中存在许多重复代码时,可使用状态模式。
代码实现
栗子:
比如公司员工,一般会有小组长,经理,总经理等职务,每个职务处理的工作内容,拥有的权限责任是不同的,不同的岗位的职责就可以通过状态模式来表示。
type RankState string const ( Employee RankState = "employee" // 员工 GroupLeader RankState = "groupLeader" // 小组长 Manager RankState = "manager" // 经理 GeneralManager RankState = "generalManager" // 总经理 ) type CompanyState interface { getRankState() RankState salary(*CompanyEmployeeMachine) int haveRight(*CompanyEmployeeMachine) []string promotion(*CompanyEmployeeMachine) } // CompanyEmployee type CompanyEmployee struct { } func (ce *CompanyEmployee) getRankState() RankState { return Employee } func (ce *CompanyEmployee) salary(cm *CompanyEmployeeMachine) int { return cm.salary } func (ce *CompanyEmployee) promotion(cm *CompanyEmployeeMachine) { cm.salary += 1000 cm.right = append(cm.right, "绩效奖金") cm.companyState = &CompanyGroupLeader{} } func (ce *CompanyEmployee) haveRight(cm *CompanyEmployeeMachine) []string { return cm.right } // CompanyGroupLeader type CompanyGroupLeader struct { } func (ce *CompanyGroupLeader) getRankState() RankState { return GroupLeader } func (ce *CompanyGroupLeader) salary(cm *CompanyEmployeeMachine) int { return cm.salary } func (ce *CompanyGroupLeader) promotion(cm *CompanyEmployeeMachine) { cm.salary += 1000 cm.companyState = &CompanyGroupLeader{} } func (ce *CompanyGroupLeader) haveRight(cm *CompanyEmployeeMachine) []string { return cm.right } type CompanyEmployeeMachine struct { salary int right []string companyState CompanyState } func InitCompanyEmployeeMachine() *CompanyEmployeeMachine { return &CompanyEmployeeMachine{ salary: 1000, right: []string{ "休假,年终奖", }, companyState: &CompanyEmployee{}, } } func (m *CompanyEmployeeMachine) HaveRight() []string { return m.companyState.haveRight(m) } func (m *CompanyEmployeeMachine) Salary() int { return m.companyState.salary(m) } func (m *CompanyEmployeeMachine) GetRankState() RankState { return m.companyState.getRankState() } func (m *CompanyEmployeeMachine) Promotion() { m.companyState.promotion(m) }
测试代码
func TestCompanyEmployee(t *testing.T) { cem := InitCompanyEmployeeMachine() fmt.Println("员工的职级", cem.GetRankState(), ";员工的薪水", cem.Salary(), ";员工的待遇", cem.HaveRight()) // 晋级 cem.Promotion() fmt.Println("员工的职级", cem.GetRankState(), ";员工的薪水", cem.Salary(), ";员工的待遇", cem.HaveRight()) }
输出的内容
员工的职级 employee ;员工的薪水 1000 ;员工的待遇 [休假,年终奖] 员工的职级 groupLeader ;员工的薪水 2000 ;员工的待遇 [休假,年终奖 绩效奖金]
结构图
参考
【文中代码】https://github.com/boilingfrog/design-pattern-learning/tree/master/状态模式
【大话设计模式】https://book.douban.com/subject/2334288/
【极客时间】https://time.geekbang.org/column/intro/100039001
【状态模式】https://boilingfrog.github.io/2021/11/23/%E4%BD%BF%E7%94%A8go%E5%AE%9E%E7%8E%B0%E7%8A%B6%E6%80%81%E6%A8%A1%E5%BC%8F/
- 设计模式学习-使用go实现单例模式
- 【设计模式】使用unity实现状态模式(State mode)
- 策略模式学习,使用go实现策略模式
- 学习php设计模式 php实现状态模式
- 从今天开始学习iOS开发(iOS 7版)--实现一款App之使用设计模式
- 学习php设计模式 php实现状态模式
- 设计模式学习(十四)————抽象工厂模式(使用Qt框架的反射技术——根据字符串动态创建类来实现)
- GoF设计模式学习之一:单例模式(Java实现)
- 设计模式应用之使用COMPOSITE模式实现流程(三)
- 设计模式- 使用抽象工厂实现多数据库切换实现过程
- JSP设计模式基础:View Helper模式——学习如何使用View Helper模式使得Model数据适应表现层的需要(2)
- 《模式——工程化实现及扩展》(设计模式C# 版)《状态模式 State》——“自我检验" 参考答案
- state设计模式学习, 一个C++的实现
- 设计模式学习----观察者模式(事件监听实现)
- 设计模式应用之使用COMPOSITE模式实现流程(二)
- HeadFirst 设计模式学习笔记11——状态模式
- 设计模式学习----观察者模式(事件监听实现)
- 转[翻译]案例学习:仅使用Redis+PHP设计实现一个简单的Twitter
- 设计模式之实现---状态模式
- 黑马程序员java学习第六天,static静态的使用及单例设计模式