`
BestUpon
  • 浏览: 294971 次
  • 性别: 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();
		}
	}
}



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

相关推荐

    状态模式 State Pattern

    ### 状态模式(State Pattern) #### 概念与定义 状态模式是一种行为设计模式,它允许对象在其内部状态改变时改变其行为,使对象看起来像是修改了它的类。该模式通过引入一个代表各种状态的类以及一个行为随着这些...

    设计模式之状态模式State

    状态模式通常包含三个主要角色:Context(上下文)、State(抽象状态)和ConcreteState(具体状态)。 上下文是拥有状态的对象,它定义了与该状态相关的接口,并负责在适当的时候将请求委托给相应的状态对象处理。...

    每天感悟总结-状态模式State

    2009-03-10模式State:一个事件(消息)引起环境或数据的变化,可能导致状态变化,于是处理流程改变,这里的状态是把处理流程分成了很多阶段,通过状态机来根据传来的事件(消息)引发状态转换,管理状态属性和状态行为,...

    设计模式C++学习之状态模式(State)

    状态模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。这种模式常用于处理对象的状态变化,并且使代码结构清晰,易于维护。 在C++中,状态模式通常包含以下几个关键...

    设计模式之状态模式(State)

    状态模式是一种行为设计模式,它使对象能够在内部状态改变时改变其行为,看起来好像改变了它的类。这种模式常用于处理对象在不同状态下表现各异的情况,避免了复杂的条件语句,提高了代码的可读性和可维护性。 在...

    状态模式(State Pattern)详解 一、状态模式简介 1.1 什么是状态模式? 1.2 为什么需要状态模式? 1.3 状态模式的核心思想 二、状态模式的结构 2.1 UML类图 2.2 各个组

    状态模式(State Pattern)详解 一、状态模式简介 1.1 什么是状态模式? 1.2 为什么需要状态模式? 1.3 状态模式的核心思想 二、状态模式的结构 2.1 UML类图 2.2 各个组件的详细说明 2.3 交互过程 三、状态模式的...

    设计模式之状态模式(State Pattern)

    状态模式是一种行为设计模式,它使你能在运行时改变对象的行为。在状态模式中,一个对象的状态变化会导致其行为的变化,这种变化不是通过改变对象的类来实现的,而是通过改变对象的状态。这个模式的核心是封装可能...

    Android的状态机模式StateMachine与State

    在博文《Android的状态机模式StateMachine与State》中,作者可能会详细介绍如何创建和使用这两种组件。通常,状态机的实现会涉及到以下步骤: 1. **定义状态接口或抽象类**:创建一个State接口或抽象类,其中包含...

    Head First 设计模式 (十) 状态模式(State pattern) C++实现

    状态模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。这种模式常用于处理对象的状态变化,并且根据不同的状态,对象的行为也相应地变化。在C++中实现状态模式,我们...

    JackChan1999#Java-Degisn-Patterns#状态模式-State Pattern1

    状态模式-State Pattern状态模式-State Pattern【学习难度:,使用频率:】状态模式-State Pattern处理对象的多种状态及其相互

    《设计模式》实战---状态模式(State Pattern)

    在《设计模式》实战---状态模式(State Pattern)这篇文章中,作者可能详细探讨了以下关键点: 1. **模式定义**:状态模式允许对象在内部状态改变时改变其行为,对象看起来好像修改了它的类。这通过将每个状态封装...

    设计模式 - 状态模式(C++实例)

    在C++中实现状态模式,我们通常会定义一个抽象状态类(State),它声明了所有可能的状态行为。然后,创建一系列具体状态类(ConcreteState)来实现这些行为。每个具体状态类代表一种特定的状态,并且在内部维护当前...

    状态模式(State Pattern)是一种行为设计模式

    状态模式(State Pattern)是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。这种模式将一个对象的行为分解为各个独立的状态,并且每个状态都封装在自己的类中,使得对象在...

    设计模式State模式源码

    State模式在实际使用中比较多,适合"状态的切换".因为我们经常会使用If elseif else 进行状态切换, 如果针对状态的这样判断切换反复出现,我们就要联想到是否可以采取State模式了. 不只是根据状态,也有根据属性.如果...

    状态模式代码示例

    在提供的压缩包`state.zip`中,很可能包含一个简单的状态模式实现,可能包括`Context`、`AbstractState`和几个`ConcreteState`类。这些类的结构可能是这样的: ```java // Context public class Context { ...

    C#面向对象设计模式纵横谈(22):(行为型模式) State 状态模式

    标题和描述均提到了"C#面向对象设计模式"中的State状态模式,这表明文章的核心内容是围绕State模式在C#编程语言中的应用展开。State模式是一种行为设计模式,旨在允许对象在其内部状态改变时,其行为也能相应地改变...

    c++状态模式

    状态模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。在C++中,状态模式通常通过定义一系列的类来表示各种状态,并用一个上下文类来管理这些状态的切换。下面将详细...

    java 设计模式之状态模式

    状态模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为,看起来好像对象改变了它的类。在Java中,状态模式通常通过定义不同的状态类和一个上下文类来实现,其中上下文类持有状态对象并调用其方法来响应...

    设计模式专题之(二十一)状态模式---设计模式状态模式示例代码(python--c++)

    状态模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。这种模式常用于处理对象的状态变化,使得对象的行为与其状态紧密相关,通过改变对象的状态,来改变对象的行为。 ...

Global site tag (gtag.js) - Google Analytics