一:相关定义
状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
二:相关类图和示例
状态模式类图:
状态模式和策略模式类图基本一致,而差别就在于它们的“意图”。我们将一群行为封装在状态对象中,context的行为随时可委托到那些状态对象中的一个。随时间流逝,当前状态在状态对象集合中游走改变,以反映出context内部的状态。
状态模式示例图:
这里以一个糖果机的状态转换作为示例来说明状态模式的应用,
在图中,糖果机对应于4种状态(不一定哦,可能会有后续的需求变更),通过不同的动作,糖果机会在这几种状态之间进行转换。在最简单的实现中,我们可以在糖果机类中定义这4种状态,然后在相关的行为方法中,通过if-else来进行状态的转换;但是,当需求进行变更时,例如多增加一种状态,我们就得在原有的糖果机代码中进行大范围的变更工作了,状态越来越多,if-else也越来越多,就越难以进行维护;下面看我们利用状态模式实现的糖果机。
public class GumballMachine {
State noQuarterState;
State hasQuarterState;
State soldState;
State soldOutState;
State state = soldOutState;
int count = 0;
public GumballMachine(int numberGumballs){
noQuarterState = new NoQuarterState(this);
hasQuarterState = new hasQuarterState(this);
soldState = new SoldState(this);
soldOutState = new soldOutState(this);
}
public void insertQuarter(){
state.insertQuarter();
}
public void ejectQuarter(){
state.ejectQuarter();
}
public void turnCrank(){
state.turnCrank();
state.dispense();
}
void setState(State state){
this.state = state;
}
void releaseBall(){
System.out.println("A gumball comes rolling out the slot...");
if(count != 0){
count = count - 1;
}
}
//每个状态的getter
}
我们用4个状态类来表示糖果机的4中状态,并将动作的调用委托给糖果机现在的状态去执行,下面是列举的两种状态:
public interface State {
void insertQuarter(); //投入25分钱
void ejectQuarter(); //退出25分钱
void turnCrank(); //转动曲柄
void dispense(); //发放糖果
}
没有25分钱
public class NoQuarterState implements State {
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 first");
}
}
有25分钱
public class HasQuarterState implements State {
GumballMachine gumballMachine;
public HasQuarterState(GumballMachine gumballMachine){
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
System.out.println("you can't insert another quarter");
}
@Override
public void ejectQuarter() {
System.out.println("Quarter returned");
gumballMachine.setState(gumballMachine.getNoQuarterState());
}
@Override
public void turnCrank() {
System.out.println("you turned...");
gumballMachine.setState(gumballMachine.getSoldState);
}
@Override
public void dispense() {
System.out.println("no gumball dispensed");
}
}
售出糖果和糖果售罄状态类似,这里就不详述了。到这里,我们的状态模式就暂时告一段落了。
参考书籍:《head first 设计模式》