调侃《First head 设计模式》之状态模式篇
来源:互联网 发布:北京淘宝供货商 编辑:程序博客网 时间:2024/05/16 01:04
现在有个糖果控制器,它的运行状态图如下:
我们要用java来实现这个糖果控制器。首先需要用一些实例变量来表示不同的状态:
我们的思路是创建一个糖果控制器类,它就像一个状态机,每个可能的操作都创建一个方法,在这些方法内部对当前状态进行判断,并做出相应的反应。
由于这并不难理解,所以直接上代码(有点长):
看起来这个系统是十分精密,无懈可击了。但是。。
需求有改变,糖果机要再曲柄转动后有10%可能性进入到赢家状态,这时候可以得到两颗糖果。
这下你有的忙了,你先要增加表示状态的实例变量,这还不算,还要在每个方法中增加赢家状态的判断和作出的相应反应,原来的系统将被改得面目全非了,如果以后再加入其他状态呢。。my god。。
之前接触过设计模式的你已经想到,要做一个可扩展性高的系统,要封装变化,要让不同状态的类解耦。
我们可以将每个状态的行为都放入一个类中,每个状态只要实现机器对应的动作就行了。糖果机在动作发生时委托给状态类。
我们创建一个状态的接口State,所有状态实现这个接口:
实现状态类:
糖果出售状态:
有25分钱状态:
糖果售罄状态留给大家去实现。
糖果机类:
看,各个方法的实现都委托给了当前状态,而当前状态在执行了委托的方法时,会做出相应的糖果机状态切换或者错误提示,这样糖果机在执行动作时,不管当前状态是什么,都执行当前状态的对应方法就行了,这样省去了冗长的判断语句。
这样我们让状态类”对修改关闭“,糖果机对”扩展开放“,可以随时加入新的状态类。
看看官方的定义:
状态模式允许对象在内部状态改变时改变它的行为,对象看起来好想修改了它的状态。
该模式将状态封装成独立的类,并将动作委托到代表当前状态的对象。
类图:
context可以随时委托到状态对象的一个,当前状态可以在状态对象集合中游走改变,而context客户对于状态对象了解不多,甚至浑然不觉。我们可以将状态模式想成不用再context中放置大量判断语句的替代方案,并大大增加了代码的可扩展性。
我们的第一个版本中,最大缺点是将状态的转换放在状态类,使得状态类间产生了依赖。
但是为此产生了很多的类,这就是为了获取弹性代码而付出的代价。
别忘了我们还有要实现的赢家状态:
在糖果机中添加赢家状态。
赢家状态类:
当有”25分钱状态“下转动曲柄有10%可能进入赢家状态,所以在“有25分钱状态”代码做一点修改就可以了:
客户端程序:
- 调侃《First head 设计模式》之状态模式篇
- 调侃《Head First设计模式》之总结篇
- 调侃《Head First设计模式》之总结篇
- 调侃《Head First 设计模式》之工厂模式(二)
- 调侃《Head First 设计模式》之单例模式
- 调侃《Head First 设计模式》之命令模式
- 调侃《Head first设计模式》之适配器模式
- 调侃《Head First设计模式》之外观模式
- 调侃《Head First设计模式》之模板方法模式
- 《Head First 设计模式》之状态模式
- Head First设计模式之状态模式
- <<Head First设计模式>>之状态模式学习篇
- 调侃《Head First设计模式》之迭代器和组合模式(一)
- 调侃《Head First设计模式》之迭代器和组合模式(二)
- Head First设计模式-状态模式
- 《Head First 设计模式》状态模式
- <Head First 设计模式>:状态模式:GumballMachine
- First-Head 设计模式:状态模式
- 关于SWT table刷新的一个解决办法
- 公共字串计算
- 《R语言与数据挖掘最佳实践和经典案例》阅读摘要
- java静态代理实现代码
- 关于某社交类app安全分析及app防止反编译的方法
- 调侃《First head 设计模式》之状态模式篇
- Linux系统中如何挂载第二块硬盘
- LeetCode 27 - Remove Element
- 统计大写字母个数
- 第二次作业:MySQL数据库及Java操作MySQL数据库
- C++链表逆序打印节点
- DNA序列
- 我们应该怎样理解动态链接库和动态链接???
- Python-1 Arithmetic expressions