状态模式定义,允许对象在自己内部状态改变时改变它的行为,对象看起来就像是修改了它的类。
该描述第一部分意思是,这个模式将状态封装进了一个独立的类,并将动作委托到对象的当前状态的状态对象。第二个部分意思就是,让客户感觉使用了对象能够改变它的行为,但是实际上这种设计模式 使用组合通过简单引用不同状态对象来造成类的改变假象。状态模式封装了一组行为。
状态模式类图
Context:是一个上下文类,可以拥有一些内部状态,并且将多个状态对象组合结合在一起。
State接口:定义了所有状态具有的共同操作,一般可以将该接口的方法和context设置一样的。
ConcreteStateA:实现了具体的状态对象,处理来自context的请求,凡是context中调用request方法,都会将该方法委托到具体的状态对象来处理。
通过在context来利用组合和多态,从而在实际的状态改变中将行为委托到具体的实现状态类中,状态模式将每一个状态的行为具体到局部化到该状态所对象的类中,免去了大量的if判断,它可以让每一个状态“对修改关闭”,让context“对扩展开放”。
一般来说,当状态转换是固定的时候,一般将状态的改变放置到context中。当转换是动态的时候,则将状态的改变放置到状态类中,状态类中应该有context的引用。
实例代码
一个糖果机,有四种不同的状态,根据不同的行为就会转换成不同的状态。
状态State接口
package com.whut.state;
publicinterface State {
void insertQuarter();
void ejectQuarter();
void turnCrank();
void dispense();
}
publicinterface State {
void insertQuarter();
void ejectQuarter();
void turnCrank();
void dispense();
}
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-----------";
}
//设置状态
publicvoid 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;
}
//获取总的数目
publicint getCount() {
return count;
}
public State getWinnerState() {
return winnerState;
}
}
//状态模式
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-----------";
}
//设置状态
publicvoid 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;
}
//获取总的数目
publicint 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
publicvoid insertQuarter() {
System.out.println("You inserted a quarter");
gumballMachine.setState(gumballMachine.getHasQuarterState());
}
@Override
publicvoid ejectQuarter() {
System.out.println("You haven't inserted a quarter");
}
@Override
publicvoid turnCrank() {
System.out.println("You turned,but there's no quarter");
}
@Override
publicvoid dispense() {
System.out.println("You need to pay a quarter first");
}
}
public class NoQuarterState implements State {
private GumballMachine gumballMachine;
public NoQuarterState(GumballMachine gumballMachine)
{
this.gumballMachine=gumballMachine;
}
@Override
publicvoid insertQuarter() {
System.out.println("You inserted a quarter");
gumballMachine.setState(gumballMachine.getHasQuarterState());
}
@Override
publicvoid ejectQuarter() {
System.out.println("You haven't inserted a quarter");
}
@Override
publicvoid turnCrank() {
System.out.println("You turned,but there's no quarter");
}
@Override
publicvoid dispense() {
System.out.println("You need to pay a quarter first");
}
}
状态模式与策略模式比较
状态模式,将一群行为封装到状态对象中,Context的行为随时可委托到那些状态对象中的一个。对象的状态改变是在内部实现的,游走于对象集合中,用户察觉不到,只是通过触发相应的行为。状态模式利用许多个不同的状态对象作为其成员属性进行组合,任何状态的改变都是事先定义好的。
策略模式,客户往往是主动指定Context所要组合的策略对象是哪一个,使得能够在运行的时候改变策略即对象的行为。可以将状态模式想成是不用在context中放置许多条件判断语句的替代方法,通过将行为包装进状态对象后,可以通过在context内部来改变状态对象来改变context的行为。策略模式通常是利用行为或者策略类来配置context类的。
本文转自 zhao_xiao_long 51CTO博客,原文链接:http://blog.51cto.com/computerdragon/1177995