不同的状态,不同的行为;或者说,每个状态有着相应的行为.
二、State模式的适用场合:
State模式在实际使用中比较多,适合"状态的切换".因为我们经常会使用If elseif else 进行状态切换, 如果针对状态的这样判断切换反复出现,我们就要联想到是否可以采取State模式了.
三、State模式与Command模式的比较:
前者从调用者和被调用者的角度出发,目的是封装被调用者的行为,让调用者只和统一的顶层接口打交道。后者从对象自身的状态出发,不涉及调用者和被调用者。是对象自身的状态切换导致的行为变化。
四、“开关切换状态” 和“ 一般的状态判断”区别:
“开关状态切换”经常发生在GUI界面的交互过程中,通过结合对象当前状态和参数,判断接下来对象应该切换到什么状态。被判断对象和被更新对象都是同一个。这一点和“一般的状态判断”是不同的,后者是根据其它对象或属性的值来更新自身的状态。被判断对象和被更新对象不是同一个。
例如:if (which==1) state="hello";
else if (which==2) state="hi";
else if (which==3) state="bye";
这是一个 " 一般的状态判断",state值的不同是根据which变量来决定的,which和state没有关系.如果改成:
if (state.euqals("bye")) state="hello";
else if (state.euqals("hello")) state="hi";
else if (state.euqals("hi")) state="bye";
这就是 "开关切换状态",是将state的状态从"hello"切换到"hi",再切换到""bye";再切换到"hello",好象一个旋转开关,这种状态改变就可以使用State模式了.
五、State模式的构成:
1.state manager 状态管理器,就是开关,如上面例子的Context实际就是一个state manager, 在state manager中有对状态的切换动作.
2.用抽象类或接口实现的父类,,不同状态就是继承这个父类的不同子类(也就是不同的状态行为)
六、State模式的例子:
状态机--父类定义
public abstract class State{ // 状态行为的父类
// 状态机需要能够感知上下文的情况,也就是之前的状态和目前的情形,所以用Context作为参数
public abstract void handlepush(Context c);
public abstract void handlepull(Context c);
public abstract void getcolor();
}
状态机--子类实现
public class BlueState extends State{
public void handlepush(Context c){
//根据push方法"如果是blue状态的切换到green" ;
c.setState(new GreenState());
}
public void handlepull(Context c){
//根据pull方法"如果是blue状态的切换到red" ;
c.setState(new RedState());
}
public abstract void getcolor(){ return (Color.blue)}
}
特点:
·拥有一个父类,表示各种不同的状态。该父类具有三个典型的方法:
·切换到上一个状态
·切换到下一个状态
·获取当前状态
·拥有一至多个子类,在子类中实现具体的状态向前、向后的切换
·如果把每个状态看成一个“状态链”上的一个独立的节点,那么有N个状态,则需要N个子类。
·如果状态只支持单向切换,则除了首尾两个状态,其它状态的节点均有两个方法,分别是向前/后一个状态的切换
·如果状态支持双向切换(例如MP3的自动循环播放功能),则尾节点可以有两个状态切换的方法
状态机管理器
public class Context{
private Sate state=null; //我们将原来的 Color state 改成了新建的State state;
//setState是用来改变state的状态 使用setState实现状态的切换,不同的状态传入不同的State,都是State的子类
pulic void setState(State state){
this.state=state;
}
public void push(){
//状态的切换的细节部分,在本例中是颜色的变化,已经封装在子类的handlepush中实现,这里无需关心
state.handlepush(this);
//因为sample要使用state中的一个切换结果,使用getColor()
Sample sample=new Sample(state.getColor());
sample.operate();
}
public void pull(){
state.handlepull(this);
Sample2 sample2=new Sample2(state.getColor());
sample2.operate();
}
}
特点:
·拥有一个状态机对象:用于代表当前的状态
·拥有一个切换到上/下一个状态的方法:实际上是调用了状态机自身的切换方法,由于状态机本身已经“知道”自己是什么状态,所以可以方便的切换到上、下一个状态。例如:state.handlePush(this)这个方法,由于此时state对象是什么类型已经知道(通过对管理器中的状态机赋值),所以切换工作就交给了对象本身了,调用者不需要知道内部是如何切换的。
·拥有一个获取当前状态的方法
我们可以看到,在状态机的上下文中,push和pull方法都把上下文本身作为参数传递给状态机,然后在状态机中调用了上下文的setState(Context c)方法。这是一个典型的Call-back(回调)机制。
七、状态机模式的优点:
(1) 封装转换过程,也就是转换规则
(2) 枚举可能的状态,因此,需要事先确定状态种类。
使用状态模式后,客户端外界可以直接使用事件Event实现,根本不必关心该事件导致如何状态变化,这些是由状态机等内部实现。这是一种Event-condition-State,状态模式封装了condition-State部分。
每个状态形成一个子类,每个状态只关心它的下一个可能状态,从而无形中形成了状态转换的规则。如果新的状态加入,只涉及它的前一个状态修改和定义。
十、状态模式和其它模式的结合应用:
从状态模式的实质:“只关心它的下一个可能状态”和客户端使用特点:“使用事件Event实现”来看,我们可以考虑将观察者模式(Observer)和状态模式(State)结合起来。被观察者在改变时发送广播消息(Event事件),观察着注意并接收该消息后,使用状态机来对当前应用的上下文进行状态的切换。