
每种事物都有不同的状态,不同的状态会有不同的表现,通过更改状态从而改变表现的设计模式称为状态模式(statepattern)
下边会通过多个例子进行讲述,会有一些代码重用的类,请注意包名!
举例1:
人有多种心情,不同的心情会有不同的表现,这里先使用分支判断写个小例子
创建一个Person类,它持有一个表示心情的字符串,通过设置这个字符串并对这个字符串进行判断来决定产生不同的行为
测试类:
输出:
这个例子的确实现了修改不同的状态而改变行为,但是代码写的不够灵活,如果添加了新的状态的时候,还需要修改大量的代码,改进版如下:
举例2:
定义Mood接口,所有心情都需要实现这个接口,Person中持有这个接口,通过set这个接口的实现类对象,来多态调用实际的perform方法
实现Mood接口的类,每个实现类的表现方法实现都不同
改进后的Person类
测试类
输出

尝试其余注释行执行的不同效果,可以发现这样实现非常灵活,只需要实现Mood接口,在测试类中传入就可以改变执行效果!细心的你可能会发现,这种结构不是策略模式的结构么?这个文章结尾会写
举例3:
人应该拥有喜悦、哀伤、无聊等状态,这些状态会在特定的时候展示出来,所以Person这个类中应该持有一个状态的集合,通过不同的传入参数来决定它的表现效果。举例2中设置Mood实现类的时候需要手动去修改Test类的代码,如果在生产环境中,我们需要改完代码、重新编译、重新部署,很麻烦,这个例子使用了配置文件
测试类:
配置文件state.properties:
输出:
配置文件中填入不同value,测试效果,如果该值未在Mood实现类中定义,那么会使用默认的happy状态。
举例4:
人有青少年、壮年、老年三个状态,过完一个状态之后会自动进入下一个状态,我们不能在人这个类中进行分支判断,那样代码实在是很糟糕,不灵活。这时我们需要抽取状态接口,状态有一个表现方法,还有一个获取下一状态的方法,这样我们只需要在实现类中指定下一状态为什么即可解决分支判断的窘境。
创建一个State接口
实现State接口的青少年、年轻人、老年
新建Person类
测试类,多次执行perform方法
输出:

这样的确实现了自动转换下一状态的功能,但是看过编程思想我们知道,java的垃圾回收器不是很勤奋的,我们每次执行nextState方法就会new一个对象,这样可能会造成内存负载过高,这样就有了柳大讲的使用枚举方法实现的状态模式,也就是这个例子的升级版
举例5:
使用枚举方式实现人的青少年、年轻人、老年状态的自动切换,解决执行举例3中的nextState方法new过多的对象问题
这里复制举例4的Person类到新包中,为什么不引用呢?因为之前的例子中已经指向了同包中的State接口,如果引用过来,我们setState会报错
枚举实现的State
测试类,因为是枚举,所以类名.元素表示实现了State接口的对象
输出:
总结:
表示每种事物中根据不同状态拥有的不同表现
拥有和策略模式相同的结构,同样是持有一个接口引用,使用这个接口引用来执行方法。
根据set方式设置具体实现类
状态模式和策略模式的区别:
相同点: 相同的代码结构
不同点:语义不同。
状态模式中的状态接口必须是这种事物紧密相关的,即只有有这种事物才会有这种状态,互相依存;而策略模式中的被执行体的接口是可以单独存在的,与代码执行的这个类之间耦合不大。比如策略模式中的cd举例,cd是一个接口,它可以单独存在,也可以和其他的播放设备发生关联。而这篇博客中的Person和State之间的关系就是互相依存的关系,状态不能单独存在。
有些时候策略模式和状态模式是含糊不清的,比如京东打折,工作日9折,周末8折,这个时候我们既可以说工作日、周末是不同的状态,也可以说不同的时间使用不同的策略
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-85284-1.html
具本人了解到国内大豆榨油
真的是让我受益匪浅的
没有申请就闯进中国被侵略者侵犯国土