状态模式
状态模式
定义
状态模式的关键是区分事物内部的状态,事物内部状态的改变往往会带来事物的行为改变
“允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类”
逗号前的意思是将状态封装成独立的类,并将请求委托给当前的状态对象,当对象的内部状态改变时,会带来不同的行为变化,比如点灯开关可以说明,在 off 和 on 这两种不同的状态下,我们点击同一个按钮,得到的行为反馈是截然不同的
逗号后面是从客户的角度来看,我们使用的对象,在不同的状态下具有截然不同的方法,这个对象看起来是从不同的类中实例化而来的,实际上这是使用了委托的效果
优点
- 状态模式定义了状态与行为之间的关系,并将它们封装在一个类里,通过增加新的状态类,很容易增加新的状态和切换
- 避免 Context 无限膨胀,状态切换的逻辑被分布在状态类中,也去掉了 context 中原本过多的条件分支
- 用对象代替字符串来记录当前状态,使得状态的切换更加一目了然
- Context 中的请求动作和状态类中封装的行为可以非常容易地独立变化而互不影响
缺点
会在系统中定义许多状态类,编写 20 个状态类是一项枯燥乏味的工作,而且系统中会因此而增加不少的对象,另外,由于逻辑分散在状态类中,虽然避开了不受欢迎的条件分支语句,但也造成了逻辑分散的问题,无法在一个地方就看出整个状态机的逻辑
优化点
有两种选择来管理 state 对象的创建和销毁,第一种是仅当 state 对象被需要时才创建并随后销毁,另一种是一开始就创建好所有的状态对象并且始终不销毁它们,如果 state 对象比较庞大,可以用第一种方式来节省内存,这样可以避免创建一些不会用到的对象,并及时地回收它们,但如果状态的改变很频繁,最好一开始就把这些 state 对象都创建出来,也没有必要销毁,因为可能很快将再次用到
状态模式和策略模式的关系
它们都封装了一系列的算法或行为,它们的类图看起来几乎一模一样,但在意图上有很大不同,因此它们是两种截然不同的模式
策略模式和状态模式的相同点是,它们都有一个上下文,一些策略或者状态类,上下文把请求委托给这些类来执行
它们之间的区别是策略模式中的各个策略类之间是平等又平行的,它们之间没有任何联系,所以客户必须熟知这些策略类的作用,以便客户可以随时主动切换算法;而在状态模式中,状态和状态对应的行为是早已封装好的,状态之间的切换也早被规定完成,“改变行为”这件事情发生在状态模式内部,对客户来说,并不需要去了解这些细节,这正是状态模式的作用所在
小结
通过状态模式重构代码之后,很多杂乱无章的代码会变得清晰