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

状态模式(State)续谈

阅读更多

前面写了一片文章:状态模式(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指正!

分享到:
评论
2 楼 ilove2009 2010-06-18  
lz表达需求有问题,交通灯状态改变,导致发出不同颜色的灯光,不管什么状态,发光这个动作是不变的但颜色会变,change这个动作是要解决的需求吗?


交通灯的状态是由什么控制的?交警or预设。

客户端是否从人的角度来考虑?目前都是用灯光颜色来指示交通,个别地方也用了声音,说不定那天用味道来指示交通也说不定呢。

我的意思是我们首先要抓住那些是变的那些是不变的。
1 楼 climber2002 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相互引用了.  应该可以重构一下. 不过只是第一念头想出来的东西, 别的地方应该还能重构一下,比如类名,方法名等等.  你的第一篇博客我没细看,也许完全的偏题了

相关推荐

    状态模式 State Pattern

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

    设计模式之状态模式State

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

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

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

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

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

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

    状态模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。在C#编程中,这种模式被广泛应用于处理具有多种状态的对象,使得对象的状态转换更加清晰和易于管理。 状态模式的...

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

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

    Android的状态机模式StateMachine与State

    状态机模式(StateMachine)在Android开发中是一种常用的设计模式,特别是在处理复杂的系统行为时,它可以帮助我们更好地组织代码,使其更具有可读性和可维护性。Android的状态机模式主要涉及两个核心概念:State...

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

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

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

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

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

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

    设计模式State模式源码

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

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

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

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

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

    c++状态模式

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

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

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

    状态机stateflow

    matlab中状态机 stateflow的详细使用方法。matlab中状态机 stateflow的详细使用方法。matlab中状态机 stateflow的详细使用方法

    java 设计模式之状态模式

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

    设计模式:状态模式TCPConnection案例

    状态模式是一种行为设计模式,它使你能在运行时改变对象的行为。在TCP连接中,状态模式的应用尤为常见,因为TCP连接在不同的阶段会有不同的行为,比如建立连接、数据传输、断开连接等。下面我们将详细探讨这个模式...

    试谈java设计模式之State.docx

    State 模式是一种行为型设计模式,它允许对象在其内部状态改变时改变其行为。该模式的主要思想是将对象的状态和行为分离,使用不同的状态子类来实现不同的行为。 何时使用 State 模式?State 模式在实际使用中非常...

Global site tag (gtag.js) - Google Analytics