状态模式定义 允许对象在自己内部状态改变时改变它的行为,对象看起来就像是修改了它的类。
该描述第一部分意思是,这个模式将状态封装进了一个独立的类,并将动作委托到对象的当前状态的状态对象。第二个部分意思就是,让客户感觉使用了对象能够改变它的行为,但是实际上这种设计模式 使用组合通过简单引用不同状态对象来造成类的改变假象。状态模式封装了一组行为。
状态模式类图
145022886.jpg
Context :是一个上下文类,可以拥有一些内部状态,并且将多个状态对象组合结合在一起。
State接口 :定义了所有状态具有的共同操作,一般可以将该接口的方法和context设置一样的。
ConcreteStateA :实现了具体的状态对象,处理来自context的请求,凡是context中调用request方法,都会将该方法委托到具体的状态对象来处理。
通过在context来利用组合和多态,从而在实际的状态改变中将行为委托到具体的实现状态类中,状态模式将每一个状态的行为具体到局部化到该状态所对象的类中,免去了大量的if判断,它可以让每一个状态“对修改关闭”,让context“对扩展开放”。
一般来说,当状态转换是固定的时候,一般将状态的改变放置到context中。当转换是动态的时候,则将状态的改变放置到状态类中,状态类中应该有context的引用。
实例代码
一个糖果机,有四种不同的状态,根据不同的行为就会转换成不同的状态。
状态State接口
package com.whut.state;

public interface State {
void insertQuarter();
void ejectQuarter();
void turnCrank();
void dispense();
}
糖果机类(context)
package com.whut.state;
//状态模式
public class GumballMachine {

private State soleOutState;
private State noQuarterState;
private State hasQuarterState;
private State soldState;
private State winnerState;

private State state=soleOutState;
private int count=0;

public GumballMachine( int count)
{
soleOutState= new SoldOutState( this);
noQuarterState= new NoQuarterState( this);
hasQuarterState= new HasQuarterState( this);
soldState= new SoldState( this);
winnerState= new WinnerState( this);
this.count=count;
if(count>0)
state=noQuarterState;
}
//投入25分的动作
public void insertQuarter()
{
state.insertQuarter();
}

//退回25分的动作
public void ejectQuarter()
{
state.ejectQuarter();
}

//转动曲柄
public void turnCrank()
{
state.turnCrank();
state.dispense();
}

//释放糖果
public void releaseBall()
{
System.out.println( "A gunmball comes rolling out the slot from machine");
if(count!=0)
count=count-1;
}

//打印机器当前状态
@Override
public String toString()
{
return "-----------"+ "\nThe machine state:"+state.toString()+ "\ncount="+count+ "\n-----------";
}

//设置状态
public void setState(State st)
{
this.state=st;
}

//获取状态
public State getSoleOutState() {
return soleOutState;
}
public State getNoQuarterState() {
return noQuarterState;
}
public State getHasQuarterState() {
return hasQuarterState;
}
public State getSoldState() {
return soldState;
}
//获取总的数目
public int getCount() {
return count;
}
public State getWinnerState() {
return winnerState;
}

}
状态实现类:
package com.whut.state;

public class NoQuarterState implements State {

private GumballMachine gumballMachine;
public NoQuarterState(GumballMachine gumballMachine)
{
this.gumballMachine=gumballMachine;
}

@Override
public void insertQuarter() {
System.out.println( "You inserted a quarter");
gumballMachine.setState(gumballMachine.getHasQuarterState());
}

@Override
public void ejectQuarter() {
System.out.println( "You haven't inserted a quarter");
}

@Override
public void turnCrank() {
System.out.println( "You turned,but there's no quarter");
}

@Override
public void dispense() {
System.out.println( "You need to pay a quarter first");
}
}
状态模式与策略模式比较
状态模式一群行为封装到状态对象中,Context的行为随时可委托到那些状态对象中的一个。对象的状态改变是在内部实现的,游走于对象集合中,用户察觉不到,只是通过触发相应的行为。状态模式利用许多个不同的状态对象作为其成员属性进行组合,任何状态的改变都是事先定义好的。
策略模式 客户往往是主动指定Context所要组合的策略对象是哪一个,使得能够在运行的时候改变策略即对象的行为。可以将状态模式想成是不用在context中放置许多条件判断语句的替代方法,通过将行为包装进状态对象后,可以通过在context内部来改变状态对象来改变context的行为。策略模式通常是利用行为或者策略类来配置context类的。