小A:“如何使用状态模式?”
大B:“状态模式可以允许客户端改变状态的转换行为,而状态机则是能够自动改变状态,状态机是一个比较独立的而且复杂的机制,具体可参考一个状态机开源项目:状态模式在工作流或游戏等各种系统中有大量使用,甚至是这些系统的核心功能设计,例如政府OA中,一个批文的状态有多种:未办;正在办理;正在批示;正在审核;已经完成等各种状态,使用状态机可以封装这个状态的变化规则,从而达到扩充状态时,不必涉及到状态的使用者。在网络游戏中,一个游戏活动存在开始;开玩;正在玩;输赢等各种状态,使用状态模式就可以实现游戏状态的总控,而游戏状态决定了游戏的各个方面,使用状态模式可以对整个游戏架构功能实现起到决定的主导作用。State需要两种类型实体参与:1、statemanager状态管理器,就是开关,如上面例子的Context实际就是一个statemanager在statemanager中有对状态的切换动作。2、用抽象类或接口实现的父类,不同状态就是继承这个父类的不同子类。”
以上面的Context为例。我们要修改它,建立两个类型的实体。
第一步:
首先建立一个父类:
publicabstractclassState{
publicabstractvoidhandlepush(Contextc);
publicabstractvoidhandlepull(Contextc);
publicabstractvoidgetcolor();
}
父类中的方法要对应statemanager中的开关行为,在statemanager中这个例子就是Context中,有两个开关动作push推和pull拉。那么在状态父类中就要有具体处理这两个动作:handlepush()handlepull();同时还需要一个获取push或pull结果的方法getcolor()。
下面是具体子类的实现:
publicclassBlueStateextendsState{
publicvoidhandlepush(Contextc){
//根据push方法“如果是blue状态的切换到green”;
c.setState(newGreenState());
}
publicvoidhandlepull(Contextc){
//根据pull方法“如果是blue状态的切换到red”;
c.setState(newRedState());
}
publicabstractvoidgetcolor(){return(Color.blue)}
}
同样其他状态的子类实现如blue一样。
第二步:
要重新改写Statemanager也就是本例的Context:
publicclassContext{
privateSatestate=null;//我们将原来的Colorstate改成了新建的Statestate;
//setState是用来改变state的状态使用setState实现状态的切换
pulicvoidsetState(Statestate){
this.state=state;
}
publicvoidpush(){
//状态的切换的细节部分,在本例中是颜色的变化,已经封装在子类的handlepush中实现,这里无需关心
state.handlepush(this);
//因为sample要使用state中的一个切换结果,使用getColor()
Samplesample=newSample(state.getColor());
sample.operate();
}
publicvoidpull(){
state.handlepull(this);
Sample2sample2=newSample2(state.getColor());
sample2.operate();
}
}
至此,我们也就实现了State的refactorying过程。
以上只是相当简单的一个实例,在实际应用中,handlepush或handelpull的处理是复杂的。