`
BestUpon
  • 浏览: 283995 次
  • 性别: Icon_minigender_1
  • 来自: 兰州
社区版块
存档分类
最新评论

状态模式(State)

阅读更多

请参看:状态模式续.

http://bestupon.iteye.com/blog/693520

 

一、引言

 

如果你现在在设计一个交通控制程序,目前可能只有三种颜色,有可能你会将其写成如下的代码形式。

TrafficLight 代码:

 

package org.bestupon.dp.state;

public class TrafficLight {
	private static enum State {
		RED, GREEN, YELLOW
	}

	private static State state = State.RED;

	public static void change() {
		switch (state) {
		case RED:
			System.out.println("红灯");
			sleep(5000);
			state = State.GREEN;
			break;
		case GREEN:
			System.out.println("绿灯");
			sleep(5000);
			state = State.YELLOW;
			break;
		case YELLOW:
			System.out.println("黄灯");
			sleep(1000);
			state = State.RED;
		}
	}

	private static void sleep(int second) {
		try {
			Thread.sleep(second);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

 

 Client代码:

 

package org.bestupon.dp.state;

public class Client {

	public static void main(String[] args) {
		while (true) {
			TrafficLight.change();
		}
	}

}
 

 

 

在以上的模式的设计基础上完成了功能,但是如果状态(红绿灯颜色)增多了呢?是不是还要修改源码呢?是不是还要修改switch语句呢?这样是不是整个流程会变得冗长呢?或者是状态是不间断的平凡的变换的呢?也就是说在{红、黄、绿}->{红、黄、绿、蓝}->{红、黄、绿、黑}->{红、黄、绿、其他}->{其他}这样不定的变换,是不是代码要平凡的修改呢?

我们终于看见了自己写的代码还是不够的灵活,那怎么才能让其变的灵活、适应各种情况呢?我们就从重构出发看看怎么解决我们的问题。

那么什么是重构呢?又如何样重构呢?

二、重构

 

重构:

 

1.       对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。

2.       使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。

3.       通俗的说法:重构是一种高效且受控的代码整理技术。

 

实现红绿灯之间状态的变化主要是依靠switch语句来改变状态的,在重构方法上有这么一条Replace Type Code with State/Strategy 这么一种手段。那么究竟是选择State模式还是Stratey模式呢?分析我们的问题主要是解决状态变化多端,而State就是(变化多端),Stratey(明修栈道、暗渡乘沧)。那么什么是状态模式呢?

 

三、状态模式

 

定义: 根据对象的状态不同,将具有不同的行为。

UML图:

 

使用时机:

         当一个对象的行为取决于他的状态,并且它必须在运行时刻根据状态改变他的行为,或者一个操作中还有庞大的多分支的条件语句,并且这些分支依赖于该对象的状态时,就需要适应状态模式。

四、分析

 

回忆上面的代码,其有很多的分支(switch语句),伴随着状态的增加,条件分支将越来越复杂,并且所依赖每一种状态都有不同的行为(每个case都有不同的动作),所以我们可以依据状态模式重构他。

下面看看,我们如何使用状态模式(State)来重构它。

五、办法

 

1.       TrafficLight 瘦身:

每一中状态抽象到一个类中去(LightState),为了每次都能很清楚的知道下一个状态是什么状态,我们设计change()中增加一个下次状态的LightState参数。

TrafficLight代码如下:

 

package org.bestupon.dp.state.refactor;
/**
 * 
 * @author BestUpon
 * @email bestupon@foxmail.com
 * @date 2010-6-15下午05:21:47
 * @ask
 * @answer
 */
public class TrafficLight {

	private LightState current = null;

	public void set(LightState state) {
		this.current = state;
	}

	public void change(TrafficLight light,LightState firstState,LightState nextState) {
		current = firstState;
		current.change(this,current);
	}
} 

 

LightState 代码如下:

package org.bestupon.dp.state.refactor;
/**
 * 
 * @author BestUpon
 * @email bestupon@foxmail.com
 * @date 2010-6-15下午05:21:00
 * @ask
 * @answer
 */
public interface LightState {
	public void change(TrafficLight light,LightState nextState);
} 

2. 增加一层对个状态的控制层, abstract Light 类:让Light 去实现LightState接口。确保状态和操作绑定在一起。

Light 代码如下:

 

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();
		}
	}
}

 

 

3. 让没一个真正的状态去实现Light这个抽象类.

//红:
package org.bestupon.dp.state.refactor;
public class RedLight extends Light {
	@Override
	public void change(TrafficLight light, LightState nextState) {
		System.out.println("红灯");
		sleep(5000);
		light.set(nextState); //考虑弹性调整状态,可以不用写死状态对象设定

}
}
//黄:
package org.bestupon.dp.state.refactor;
public class YellowLight extends Light {

	@Override
	public void change(TrafficLight light,LightState nextState) {
		System.out.println("黄灯");
		sleep(1000);
		light.set(nextState);
	}
}
//绿:
package org.bestupon.dp.state.refactor;
public class GreenLight extends Light {

	public void change(TrafficLight light, LightState nextState) {
		System.out.println("绿灯");
		sleep(5000);
		light.set(nextState);

	}
}

 

 

 4.客户端

 

 

package org.bestupon.dp.state.refactor;
/**
 * 
 * @author BestUpon
 * @email bestupon@foxmail.com
 * @date 2010-6-15下午05:23:47
 * @ask 
 * @answer
 */
class Client {
	public static void main(String[] args) {

		TrafficLight trafficLight = new TrafficLight();

		// LightState states [] = {new RedLight(), new YellowLight(), new GreenLight(),new YellowLight() };
		LightState states[] = StateHolder.getStates();

		int index = 0;
		while (index != states.length) {
			trafficLight.change(trafficLight, states[index], index == states.length - 1 ? states[index] : states[index + 1]);
			index++;
			if (index == states.length)
				index = 0;
		}
	}
}
 

 

5.为了在下次修改状态和状态次序的时候不修改客户端,将其封装在了一个工具类中StateHolder中。

 

package org.bestupon.dp.state.refactor;
/**
 * 
 * @author BestUpon
 * @email bestupon@foxmail.com
 * @date 2010-6-15下午08:11:33
 * @ask
 * @answer
 */
public class StateHolder {
	private static LightState[] states = null;
	public static LightState[] getStates(){
		if(null == states) {
			LightState[]statestemp= {new RedLight(), new YellowLight(), new GreenLight(),new YellowLight() };
			states = statestemp;
		}
		return states;
	}
}

 优点

         状态模式使用代码中复杂而庸长的逻辑判断语句问题得到了解决,而且状态角色将具体的状态和他对应的行为封装了起来,这使得增加一种新的状态显得十分简单。

      缺点:

         使用状态模式时,每个状态对应一个具体的状态类,使结构分散,逻辑不太清楚,阅读代码时比较困难。

         评论:

现在线程是休眠时间直接写在了类中,本程序依然还有重构的价值!

 

附件:源程序doc文档

 

 

 

 

 

 

 

  • 大小: 21.5 KB
分享到:
评论
26 楼 xue_lang 2014-10-27  
看了半天,有点坑爹的赶脚,哎
25 楼 teacup_madman 2014-04-21  
我只能说。这个程序可以去掉的地方太多了。这个真的是State模式吗? 看到main()方法后,我失去了兴趣,这个while里完全都是重新复制,而不是状态的直接切换,
 public void change(TrafficLight light,LightState firstState,LightState nextState)

这个上面LightState nextState,这个参数有什么用?

 public void set(LightState state) {  
        this.current = state;  
    }  


这个方法有和没有,有神马区别?

写了那么多代码,最后还是直接用while去push值,和第一个示例雷同。

我不知道这个程序的参考价值是什么。。

我水平不够。。看不出这个像一个状态的切换.....
24 楼 冬日的阳光 2013-12-05  
TrafficLight这个类的change方法可以改一下,如下:
public class TrafficLight {
	private LightState current = null;

	public TrafficLight(LightState current) {
		super();
		this.current = current;
	}

	public void set(LightState state) {
		this.current = state;
	}

	public void change(LightState nextState) {
		current.change(this, nextState);
	}
}


在client中这样调用:
//红,黄,绿,黄,
		int index = 0;
		TrafficLight trafficLight = new TrafficLight(states[index++]);
		while (true) {
			trafficLight.change(states[index]);
			index++;
			if (index == states.length)
				index = 0;
		}
23 楼 冬日的阳光 2013-12-05  
抛出异常的爱 写道
iaimstar 写道
BestUpon 写道

参看了以上的写法.没错,这正是所有的讲解状态模式的典型例子写法,我在前面也是这么写的,但是我觉得状态之间的转换不够灵活,没有将下一个状态写死了,这样可以随时灵活的调整!比如红灯亮结束后,不是绿灯亮了,而是黄灯,或是增加了一种灯(蓝)灯!就不好控制了!修改的地方也多了!


然后当状态多了以后,你就开始怀念典型的状态模式了。

而且没有什么不灵活的,修改发生变化的状态就可以了,而不用去关心其他没有变化的状态


状态模式一般使用都是有多个对应动作的例子才好看....
只有一个change方法的例子叫他状态模式那多不合算

你可以试试里面有三四个方法.
的状态模式.
用其它的方式来的代价会大的多.

PS:放在一个list里顺序调用是观查者模式的特点


可以改为这个:
LightState states[] = StateHolder.getStates();
//红,黄,绿,黄,
int index = 0;
TrafficLight trafficLight = new TrafficLight(states[index++]);
while (true) {
trafficLight.change(trafficLight,states[index]);
index++;
if (index == states.length)
index = 0;
}

第一次的状态不用在方法中体现,在初始化TrafficLight的时候给定:
public class TrafficLight {
private LightState current = null;

public TrafficLight(LightState current) {
super();
this.current = current;
}

public void set(LightState state) {
this.current = state;
}

public void change(TrafficLight light, LightState nextState) {
current.change(this, nextState);
}
}
22 楼 冬日的阳光 2013-12-05  
zjshan 写道
BestUpon 写道
lj9799616 写道
在你的Client里面
trafficLight.change(trafficLight, states[index], index == states.length - 1 ? states[index] : states[index + 1]);

这句当index==3时所指的nextState是不是不对啊  指向了currentState


package org.bestupon.dp.state.refactor;
/**
*
* @author BestUpon
* @email bestupon@foxmail.com
* @date 2010-6-15下午05:23:47
* @ask 状态模式客户端
* @answer
*/
class Client {
public static void main(String[] args) {

TrafficLight trafficLight = new TrafficLight();
LightState states[] = StateHolder.getStates();
int index = 0;
while (true) {
if(index != states.length)
{
trafficLight.change(trafficLight, states[index], index == states.length - 1 ? states[0] : states[index+1]);
index++;
}else
{
index=0;
}


}
}
}

目的就是在列出的状态中间循环,如果是最后一个状态的话,就返回到第一个状态在做循环!是按照前面的没有重构之前的意图有意这样写的,要不循环就停止了!


trafficLight.change(trafficLight, states[index], index == states.length - 1 ? states[index] : states[index + 1]);
方法中第三个参数应该是没有用的,所以index == states.length - 1 ? states[index] : states[index + 1]怎么写结果都是一样的。O(∩_∩)O~

可以改为这个:
LightState states[] = StateHolder.getStates();
//红,黄,绿,黄,
int index = 0;
TrafficLight trafficLight = new TrafficLight(states[index++]);
while (true) {
trafficLight.change(trafficLight,states[index]);
index++;
if (index == states.length)
index = 0;
}
第一次的状态不用在方法中体现,在初始化TrafficLight的时候给定:
public class TrafficLight {
private LightState current = null;

public TrafficLight(LightState current) {
super();
this.current = current;
}

public void set(LightState state) {
this.current = state;
}

public void change(TrafficLight light, LightState nextState) {
current.change(this, nextState);
}
}
21 楼 sailinglxg 2010-06-18  
对抛哥代码修改了一下
/**
 * 定义枚举类
 * @author 
 *
 */
public enum EnumLight {
	红灯(500), 黄灯(100), 绿灯(500),蓝灯(300);

	int sleepping;
	int min;//循环次数下线
	int max;//循环次数上线

	private EnumLight(int x) {
		this.sleepping = x;
	}

}

/**
 * 定义灯的抽象类
 * @author 
 *
 */
public abstract class Light {
   public abstract void sleep();
   public abstract void change();
   
   /**
	 * 判断是否要限制循环
	 * @param min
	 * @param max
	 * @param isLimited
	 * @return
	 */
	public boolean isLooped(int min,int max, boolean isLimited){
		return (isLimited == true) ? (min < max) && isLimited : true;
	}
}

/**
 * 采用枚举实现状态模式
 * 
 * @author 
 * 
 */
public class TrafficLight extends Light {
	private EnumLight el;

	public TrafficLight(EnumLight el) {
		this.el = el;
	}

	/**
	 * 改变状态
	 */
	public void change() {
		System.out.println(el);
		sleep();
		this.el = el.values()[(el.ordinal() + 1) % el.values().length];
		this.el.min++;
	}

	@Override
	public void sleep() {
		try {
			Thread.sleep(el.sleepping);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		EnumLight el = EnumLight.红灯;
		el.min = 0;// 循环次数下线
		el.max = 4;// 循环次数上线
		TrafficLight tl = new TrafficLight(el);

		boolean isLimited = false;// 是否需要限制上线下线
		boolean isLooped = tl.isLooped(el.min, el.max, isLimited);

		while (isLooped) {
			isLooped = tl.isLooped(el.min, el.max, isLimited);
			tl.change();
		}
	}
}
20 楼 sailinglxg 2010-06-18  
感觉还是抛哥写得比较犀利
抛出异常的爱 写道

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();
		}
	}
}

19 楼 coffeesweet 2010-06-18  
我觉得楼主的写法和把状态存在配置文件或是数据库里的效果是一样的,
抛出的写的不错!
18 楼 cxr1217 2010-06-18  
抛出异常的爱 写道
BestUpon 写道
iaimstar 写道
枚举各种万能
既然你用了枚举,为啥不用枚举来写状态模式


枚举虽然遍历的时候也是以自然顺序的,但是直观上数组的顺序性比较直观!也容易理解上一个状态和下一个状态的关系!



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();
		}
	}
}



异常哥有宝贝儿了?恭喜恭喜恭喜~
17 楼 BestUpon 2010-06-18  
zjshan 写道

trafficLight.change(trafficLight, states[index], index == states.length - 1 ? states[index] : states[index + 1]);
方法中第三个参数应该是没有用的,所以index == states.length - 1 ? states[index] : states[index + 1]怎么写结果都是一样的。O(∩_∩)O~


写第三个参数的意思是传递的是下一个状态的待以后重构的时候扩充的(当初的想法是:灵活的支出上一个状态(第一个状态),下一个状态!代码没有重构,就直接发了!惭愧!)。这里写states[index+1],只是举例,说明了一种情况,不一定非要是states[index+1],也可以是states[index%2]等等,还可以手动的写!new LightState()的对象,至于你使用if...else 语句是没有错,但是依据个人习惯,个人习惯是只写if很少使用if..else,将错误遏制在萌芽阶段!
也可以写成:
trafficLight.change(trafficLight, states[index]);还可以写成:trafficLight.change(trafficLight,index == states.length - 1 ? states[0] : states[index + 1]);
见谅!
16 楼 zjshan 2010-06-17  
BestUpon 写道
lj9799616 写道
在你的Client里面
trafficLight.change(trafficLight, states[index], index == states.length - 1 ? states[index] : states[index + 1]);

这句当index==3时所指的nextState是不是不对啊  指向了currentState


package org.bestupon.dp.state.refactor;
/**
*
* @author BestUpon
* @email bestupon@foxmail.com
* @date 2010-6-15下午05:23:47
* @ask 状态模式客户端
* @answer
*/
class Client {
public static void main(String[] args) {

TrafficLight trafficLight = new TrafficLight();
LightState states[] = StateHolder.getStates();
int index = 0;
while (true) {
if(index != states.length)
{
trafficLight.change(trafficLight, states[index], index == states.length - 1 ? states[0] : states[index+1]);
index++;
}else
{
index=0;
}


}
}
}

目的就是在列出的状态中间循环,如果是最后一个状态的话,就返回到第一个状态在做循环!是按照前面的没有重构之前的意图有意这样写的,要不循环就停止了!


trafficLight.change(trafficLight, states[index], index == states.length - 1 ? states[index] : states[index + 1]);
方法中第三个参数应该是没有用的,所以index == states.length - 1 ? states[index] : states[index + 1]怎么写结果都是一样的。O(∩_∩)O~
15 楼 抛出异常的爱 2010-06-17  
iaimstar 写道
BestUpon 写道

参看了以上的写法.没错,这正是所有的讲解状态模式的典型例子写法,我在前面也是这么写的,但是我觉得状态之间的转换不够灵活,没有将下一个状态写死了,这样可以随时灵活的调整!比如红灯亮结束后,不是绿灯亮了,而是黄灯,或是增加了一种灯(蓝)灯!就不好控制了!修改的地方也多了!


然后当状态多了以后,你就开始怀念典型的状态模式了。

而且没有什么不灵活的,修改发生变化的状态就可以了,而不用去关心其他没有变化的状态


状态模式一般使用都是有多个对应动作的例子才好看....
只有一个change方法的例子叫他状态模式那多不合算

你可以试试里面有三四个方法.
的状态模式.
用其它的方式来代换的代价会大的多.

PS:放在一个list里顺序调用是观查者模式的特点
14 楼 iaimstar 2010-06-17  
BestUpon 写道

参看了以上的写法.没错,这正是所有的讲解状态模式的典型例子写法,我在前面也是这么写的,但是我觉得状态之间的转换不够灵活,没有将下一个状态写死了,这样可以随时灵活的调整!比如红灯亮结束后,不是绿灯亮了,而是黄灯,或是增加了一种灯(蓝)灯!就不好控制了!修改的地方也多了!


然后当状态多了以后,你就开始怀念典型的状态模式了。

而且没有什么不灵活的,修改发生变化的状态就可以了,而不用去关心其他没有变化的状态

13 楼 BestUpon 2010-06-17  
iaimstar 写道
我自己写了一个另外一个形式的
package com.designPattern.state;

public enum State {
	RED("红灯", 2000) {
		@Override
		public State change() {
			return GREEN;
		}
	},
	GREEN("绿灯", 1000) {
		@Override
		public State change() {
			return YELLOW;

		}
	},
	YELLOW("黄灯", 500) {
		@Override
		public State change() {
			return RED;
		}
	};
	private int wait;
	private String statname;

	public abstract State change();

	public State changeState() {
		System.out.println(statname);
		try {
			Thread.sleep(wait);
		} catch (InterruptedException e) {
			System.out.println("wrong");
		}
		return change();
	}

	private State(String name, int wait) {
		statname = name;
		this.wait = wait;
	}

	public String getStatname() {
		return statname;
	}

	public static void main(String[] args) {
		GREEN.changeState();
		GREEN.changeState().changeState();
		GREEN.changeState().changeState().changeState();
	}

	public void setWait(int wait) {
		this.wait = wait;
	}

	public int getWait() {
		return wait;
	}
}


可能这也是比较正统的状态模式的实现,但是实际上,枚举和lz的状态模式都有些问题

状态模式最大的特点是能在运行期间动态的改变行为,而作为状态的对象则不依赖于其他对象而独立变化。

枚举的问题很明显,增加修改状态都很麻烦,而将状态切分成不同的类可以更灵活的添加和修改状态。

lz的状态模式我则觉得有些问题,状态模式的好处正是状态对象本身可以通过context独立转换,比如,当红灯结束的时候绿灯亮起,状态的迁移由状态本身来完成。

而lz的状态模式更像是chain,通过预先定义好下一个chain(state)在执行已有的状态迁移逻辑,个人觉得并不能算是动态的改变行为,反而有点画蛇添足,而且也没有state本身来指定nextstate来的灵活。
这样做虽然解耦了 几种状态,但是却降低了可读性,我个人不太推荐



参看了以上的写法.没错,这正是所有的讲解状态模式的典型例子写法,我在前面也是这么写的,但是我觉得状态之间的转换不够灵活,没有将下一个状态写死了,这样可以随时灵活的调整!比如红灯亮结束后,不是绿灯亮了,而是黄灯,或是增加了一种灯(蓝)灯!就不好控制了!修改的地方也多了!
12 楼 iaimstar 2010-06-17  
抛出异常的爱 写道
PS: 这个不是状态模式的例子.

要算也应该算是迭代器的一种变型.仔细看里面有next()方法的.


老抛说的对, 不过我觉得更像责任链、、
11 楼 iaimstar 2010-06-17  
我自己写了一个另外一个形式的
package com.designPattern.state;

public enum State {
	RED("红灯", 2000) {
		@Override
		public State change() {
			return GREEN;
		}
	},
	GREEN("绿灯", 1000) {
		@Override
		public State change() {
			return YELLOW;

		}
	},
	YELLOW("黄灯", 500) {
		@Override
		public State change() {
			return RED;
		}
	};
	private int wait;
	private String statname;

	public abstract State change();

	public State changeState() {
		System.out.println(statname);
		try {
			Thread.sleep(wait);
		} catch (InterruptedException e) {
			System.out.println("wrong");
		}
		return change();
	}

	private State(String name, int wait) {
		statname = name;
		this.wait = wait;
	}

	public String getStatname() {
		return statname;
	}

	public static void main(String[] args) {
		GREEN.changeState();
		GREEN.changeState().changeState();
		GREEN.changeState().changeState().changeState();
	}


}


可能这也是比较正统的状态模式的实现,但是实际上,枚举和lz的状态模式都有些问题

状态模式最大的特点是能在运行期间动态的改变行为,而作为状态的对象则不依赖于其他对象而独立变化。

枚举的问题很明显,增加修改状态都很麻烦,而将状态切分成不同的类可以更灵活的添加和修改状态。

lz的状态模式我则觉得有些问题,状态模式的好处正是状态对象本身可以通过context独立转换,比如,当红灯结束的时候绿灯亮起,状态的迁移由状态本身来完成。

而lz的状态模式更像是chain,通过预先定义好下一个chain(state)在执行已有的状态迁移逻辑,个人觉得并不能算是动态的改变行为,反而有点画蛇添足,而且也没有state本身来指定nextstate来的灵活。
这样做虽然解耦了 几种状态,但是却降低了可读性,我个人不太推荐
10 楼 BestUpon 2010-06-17  
抛出异常的爱 写道
PS: 这个不是状态模式的例子.

要算也应该算是迭代器的一种变型.仔细看里面有next()方法的.


写这个例子,主要是练习使用State模式和Strategy 模式 做重构,还在学习阶段!希望不要见笑!以后多多指教!
9 楼 BestUpon 2010-06-17  
lj9799616 写道
在你的Client里面
trafficLight.change(trafficLight, states[index], index == states.length - 1 ? states[index] : states[index + 1]);

这句当index==3时所指的nextState是不是不对啊  指向了currentState


package org.bestupon.dp.state.refactor;
/**
*
* @author BestUpon
* @email bestupon@foxmail.com
* @date 2010-6-15下午05:23:47
* @ask 状态模式客户端
* @answer
*/
class Client {
public static void main(String[] args) {

TrafficLight trafficLight = new TrafficLight();
LightState states[] = StateHolder.getStates();
int index = 0;
while (true) {
if(index != states.length)
{
trafficLight.change(trafficLight, states[index], index == states.length - 1 ? states[0] : states[index+1]);
index++;
}else
{
index=0;
}


}
}
}

目的就是在列出的状态中间循环,如果是最后一个状态的话,就返回到第一个状态在做循环!是按照前面的没有重构之前的意图有意这样写的,要不循环就停止了!
8 楼 抛出异常的爱 2010-06-17  
PS: 这个不是状态模式的例子.

要算也应该算是迭代器的一种变型.仔细看里面有next()方法的.
7 楼 BestUpon 2010-06-17  
抛出异常的爱 写道
BestUpon 写道
iaimstar 写道
枚举各种万能
既然你用了枚举,为啥不用枚举来写状态模式


枚举虽然遍历的时候也是以自然顺序的,但是直观上数组的顺序性比较直观!也容易理解上一个状态和下一个状态的关系!



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();
		}
	}
}



不错!写的相当的好!完了我再重构下!

相关推荐

Global site tag (gtag.js) - Google Analytics