02-状态模式

1 作用

允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。(这里的对象指的就是模型中的Context,行为指的就是State的子类)

2 例子

考虑一个问题:实现一个表示网络连接的类TCPConnection,它的对象的状态处于若干不同状态之一:连接已建立(Established)、正在监听(Listening)、连接已关闭(Closed)。当一个TCPConection对象收到其他对象的请求时,他根据自身的状态做出不同的反应。例如,一个Open请求的结果依赖于该连接时处于连接已关闭还是连接已建立的状态。状态模式描述了TCPConnextion如何在每一个状态下表现出不同的行为。

实现方法:关键思想是在TCPConnection引入一个TCPState的抽象类来表示网络连接的状态。TCPState类为各个不同的状态声明了一个(或一套)公共的接口。针对每个状态的行为实现TCPState的子类。例如,TCPEstablished和TCPClosed类分别实现了特定于TCPConnection的连接已建立状态和连接已关闭状态的行为。

TCPConnection
-TCPState tpcState;
open()
acknowledge()
close()
«interface»
TCPState
open()
acknowledge()
close()
TCPOpen
open()
acknowledge()
close()
TCPEstablished
open()
acknowledge()
close()
TCPClosed
open()
acknowledge()
close()

TCPConnection类维护一个表示TCP连接当前状态的状态对象(一个TCPState子类的实例)。TCPConnection类将所有与状态相关的请求委托给这个状态的对象。TCPConnection使用它 的TCPState子类实例来执行特定于连接状态的操作。
一旦连接状态改变,TCPConnection对象就会改表它所使用的状态对象。例如当连接从已建立状态转位已关闭状态时,TCPConnection会用一个TCPClosed的实例来代替原来的TCPConnextion的实例,至于怎么替换,一般是在一个状态结束的时候掉用给TCPConnextion的TCPState变量设置成另外一个状态类实例。

2 使用场景

  • 对象的行为取决于它的状态。并且它必须在运行的时根据状态改变它的行为。
  • 一个操作中含有大量的多分支的条件语句,并且这些分支依赖于该对象的状态。这个状态通常有一个或者多个枚举常量表示。通常,多个操作包含这一相同的条件结构。State模式将每个条件分支放入一个独立的类中。

3 结构

Context
-State state
«interface»
State
+operate()
StateA
+operate()
StateB
+operate()
StateC
+operate()

从结构看和策略模式一摸一样,但实际上实现起来并不一样,策略模式各个子类间可以说是完全独立的,策略模式的行为需要外部进行指定或者说提供相应的参数获取,而状态模式各个子类间是紧密关联的,状态之间是相互转化的,各个状态子类之间组合出一个完整的行为,通常来说他们之间还会互相依赖,因为Context从一个状态到另一个状态的转变时需要在状态子类中实现。
以下《Head_First 设计模式》对策略模式和状态模式区别的描述————
在这里插入图片描述

4 状态模式和状态机

两者区别可以参考:https://blog.csdn.net/qq_43413788/article/details/122969822
状态机可以是一个很广泛的概念,一张状态图或者一个具体的机器、一段实现了状态流转图的代码也算是状态机,这里我们只讨论用代码实现状态流转的状态机,如Spring开源的状态机org.springframework.statemachine;
可以使用状态模式来实现状态机,但并不是状态机一定是使用状态模式来实现;

4.1 使用状态模式实现的简易状态机

请参考:https://www.jianshu.com/p/8def04b34b3c
有的同学可能说这个并没有使用到状态模式,因为它没有用到上面第3小节说到的机构。确实这个例子没有严格使用到状态模式所定义的固定结构,但我认为这个结构定义的只是一种思想:我们可以把各种状态独立的封装起来,这个封装可以是一个类,也可以是一个子模块,当然Context也是。
参考的简易状态机中,StatusHandler就相当于结构中的State接口,用于封装各个状态该做的事情;请假单LeavePermit就相当于Context,用于保存当前状态机实例的上下文;

5《Head_First 设计模式》状态模式章节的读后感

书本中的例子描述的只是一个单机的程序,糖果机运行只需要一个程序实例就行,其中的上下文保存的就是当前这一台机器的状态,关机后可能状态都没有了。刚开始看的时候感觉这根本不符合我们后端开发的使用场景,但再结合状态机进一步理解后,明白了糖果机只是状态模式的简单应用,某种角度上也是一个简易的状态机,在我们后端工程中,一个“糖果机”开发好后,可能会同时有多个实例在执行,例如可能会同时有多个订单(加入购物车->待提交订单->提交订单->待支付->支付->待发货->发快递->发货中->待签收->签收->已签收)在执行,而且在某个状态State或Even执行完后还需要将上下文持久化到数据库中。
在实际工程中,我们单独用到状态模式的情况应该会很少,像这种状态流转的情况,我们可能直接就采用了状态机(例如Spring提供的状态机)中间件去解决下单这种场景就很方便,或者流程引擎(比如activity、flowable——流程引擎也是基于状态机实现的)

PS:像springframework.statemachine笼统的说是状态机,但用它实现的具体某个状态转换程序也是一个状态机,比如上面简易状态机中,实现的事假程序是一个状态机,实现的年假程序是另一个状态机。

—— 以上都是个人学习过程中的一些浅见,希望大家多多批评指教。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值