浏览 2307 次
锁定老帖子 主题:状态模式(State)续谈
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-06-18
最后修改:2010-06-18
前面写了一片文章:状态模式(state)http://bestupon.iteye.com/blog/692913。各位JE好友提出了很多宝贵的意见和建议。尤其是“抛出异常的爱”。 关于红绿灯等状态之间的转换我的写法是:
package org.bestupon.dp.state.refactor; /** * * @author BestUpon * @email bestupon@foxmail.com * @date 2010-6-15下午05:21:15 * @ask * @answer */ public abstract class Light implements LightState { @Override public abstract void change(TrafficLight light, LightState nextState); protected void sleep(int second) { try { Thread.sleep(second); } catch (InterruptedException e) { e.printStackTrace(); } } } 在重新改写之后客户端调用如下:
class Client { public static void main(String[] args) { TrafficLight trafficLight = new TrafficLight(); LightState states[] = StateHolder.getStates(); int index = 0; while (index != states.length) { trafficLight.change(trafficLight, states[index]); // trafficLight.change(trafficLight, states[index%2]);//取出下标为index mod 2 的那个状态 // trafficLight.change(trafficLight, new YellowLight());// 每次重新创建一个对象 // trafficLight.change(trafficLight,index == states.length - 1 ? states[0] : states[index + 1]);//取出下一个数组元素做状态 index++; if (index == states.length) index = 0; } } } 可以方便的更改下一个状态是怎么样的! 对于老抛提出了如下写法:
enum Light{ 红灯(1000),黄灯(5000),绿灯(5000); //顺序调整. int sleepping; private Light(int x) { this.sleepping = x ; } public Light change(){ System.out.println(name()); sleep(); return next(); } public Light next(){ return values()[((ordinal()+1)%(values().length))]; } public static void main(String[] args) { Light light = Light.红灯; while(true){ light = light.change(); } } private void sleep() { try { Thread.sleep(this.sleepping); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 还有其他好友给出的代码,都让我前面写的: index == states.length - 1 ? states[0] : states[index + 1] 取出下一个元素的一种情况给误导了, 大家都认为是遍历数组就可以了! 对于“iaimstar”JEer,说的:
可能这也是比较正统的状态模式的实现,但是实际上,枚举和lz的状态模式都有些问题 状态模式最大的特点是能在运行期间动态的改变行为,而作为状态的对象则不依赖于其他对象而独立变化。 枚举的问题很明显,增加修改状态都很麻烦,而将状态切分成不同的类可以更灵活的添加和修改状态。 lz的状态模式我则觉得有些问题,状态模式的好处正是状态对象本身可以通过context独立转换,比如,当红灯结束的时候绿灯亮起,状态的迁移由状态本身来完成。 而lz的状态模式更像是chain,通过预先定义好下一个chain(state)在执行已有的状态迁移逻辑,个人觉得并不能算是动态的改变行为,反而有点画蛇添足,而且也没有state本身来指定nextstate来的灵活。
个人认为: 客户端传递给的nexeState,虽然每次要指定给context,下一个状态是什么,这也利用了状态模式运行期间依靠动态的改变自身的状态,来决定自己的行为的特性。像“iaimstar”给出的应该是定向线路的话,个人觉得,指定next更像是随机线路,如果说一个是直线的话,那么另一个将是点集。或者其他,但是没有影响对象的行为,应为行为和状态是绑定在一起的,状态改变的话,行为必然是会变!
或许我的理解还有很大的问题!还望各位JEer指正! 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-06-18
最后修改:2010-06-18
BestUpon 写道 public abstract class Light implements LightState { @Override public abstract void change(TrafficLight light, LightState nextState); protected void sleep(int second) { try { Thread.sleep(second); } catch (InterruptedException e) { e.printStackTrace(); } } } 你这段代码我觉得有这么几个问题, 1. Light 为什么要继承 LightState, 两者根本不是一个概念, 2. Light 跟 TrafficLight 是什么关系,两者从概念上感觉是一个东西, 是不是笔误? 3. change 方法的两个参数看不出是干什么用的, 是要把第一个参数light的状态设成nextState, 还是要把当前的this的状态设成nextState ? 我自己的第一直觉是这么想的 public class LightScheduler { private Light light; /** Ask the light to change state after millisecond */ public void scheduleChange(int millisecond) { .... } /**Triggered by a timer */ public void trigger() { light.stateChange(); } } public class Light { public static final LightState RED = new RedState(...); public static final LightState YELLOW = new YellowState(...); public static final LightState GREEN = new GreenState(...); private LightState state = RED; private LightScheduler sheduler; public void stateChange() { state.stateChange(this); } public void setState(LightState state) { this.state = state; } public void scheduleChange(int millsecond) { this.scheduler.scheduleChange(millisecond); } } public interface LightState { public void stateChange(Light light); } public class RedState implements LightState { public void stateChange(Light light) { light.setState(Light.GREEN); // Now red becomes green light.sheduleChange(5 * 60 * 1000) ; //5 minutes to change to another state,such as yellow } } // class YellowState ... // class GreenState ... 用一个类LightScheduler用来触发Light的状态改变,里面维护了一个类似定时器的东西, LightScheduler.scheduleChange 方法告知定时器多长时间后触发Light的stateChange函数, Light把这个方法delegate给自己的state,有state来决定下一个状态是什么,并且多长时间去触发下一次状态改变. Light的三个状态作为static常量. 要运行就往Scheduler里面schedule一次就可以自动运行了. 当然如果不用scheduler直接用sleep也可以,但不管怎样Light.change函数的两个参数感觉没有必要,因为应该是Light的currentState来决定下一个State是什么,也就是由Subject当前的Context以及外部对它的调用来决定下一个状态是什么,而不是只由Light的调用者决定. 这儿有一个问题是Light跟LightScheduler相互引用了. 应该可以重构一下. 不过只是第一念头想出来的东西, 别的地方应该还能重构一下,比如类名,方法名等等. 你的第一篇博客我没细看,也许完全的偏题了 |
|
返回顶楼 | |
发表时间:2010-06-18
lz表达需求有问题,交通灯状态改变,导致发出不同颜色的灯光,不管什么状态,发光这个动作是不变的但颜色会变,change这个动作是要解决的需求吗?
交通灯的状态是由什么控制的?交警or预设。 客户端是否从人的角度来考虑?目前都是用灯光颜色来指示交通,个别地方也用了声音,说不定那天用味道来指示交通也说不定呢。 我的意思是我们首先要抓住那些是变的那些是不变的。 |
|
返回顶楼 | |