通过修改类的内部状态来修改类的行为。调用一个对象的方法时会改变对象内部的状态,下次再调用这个对象的方法,会调用新的状态下的对象的方法。
经典的投币机例子,看下类图:(我发现想要写好代码一定要先设计好,要学习画UML图了...)
上面的类图中我们可以找到四个状态:未投币 - 已投币 - 商品售出 - 商品售罄。
四个状态存在于一个环境(Context):投币机
这个投币机有三个动作:投币 - 退币 - 抽奖(这里我加了一个领取的状态)
//状态接口,包含所有动作,用于实现不同的状态
public interface BaseState {
/**
* 投币
*/
void coin();
/**
* 退款
*/
void refund();
/**
* 抽奖
*/
void lottery();
/**
* 领取
*/
void award();
}
//未投币状态
public class NoMoneyState implements BaseState {
//投币机
private VehicleMachine vehicleMachine;
public NoMoneyState(VehicleMachine vehicleMachine) {
this.vehicleMachine = vehicleMachine;
}
@Override
public void coin() {
System.out.println("投币成功");
vehicleMachine.setCurrentState(vehicleMachine.getHasMoneyState());
}
@Override
public void refund() {
System.out.println("尚未投币,无法退款");
}
@Override
public void lottery() {
System.out.println("尚未投币,无法抽奖");
}
@Override
public void award() {
System.out.println("尚未投币,无法领奖");
}
}
//已投币状态
public class HasMoneyState implements BaseState {
private VehicleMachine vehicleMachine;
public HasMoneyState(VehicleMachine vehicleMachine) {
this.vehicleMachine = vehicleMachine;
}
@Override
public void coin() {
System.out.println("已经投过币了");
}
@Override
public void refund() {
System.out.println("已经退款");
vehicleMachine.setCurrentState(vehicleMachine.getNoMoneyState());
}
@Override
public void lottery() {
if (vehicleMachine.getGoodCount() <= 0) {
System.out.println("商品已售罄");
refund();
} else {
System.out.println("正在出货");
vehicleMachine.setCurrentState(vehicleMachine.getSolingState());
}
}
@Override
public void award() {
System.out.println("正在出货");
}
}
//正在出货状态
public class SolingState implements BaseState {
private VehicleMachine vehicleMachine;
public SolingState(VehicleMachine vehicleMachine) {
this.vehicleMachine = vehicleMachine;
}
@Override
public void coin() {
System.out.println("正在出货,请稍后");
}
@Override
public void refund() {
System.out.println("正在出货,请稍后");
}
@Override
public void lottery() {
System.out.println("正在出货,请稍后");
}
@Override
public void award() {
System.out.println("商品已领取");
int count = vehicleMachine.getGoodCount();
vehicleMachine.setGoodCount(--count);
vehicleMachine.setCurrentState(vehicleMachine.getNoMoneyState());
}
}
//售罄状态
public class SoldOutState implements BaseState {
private VehicleMachine vehicleMachine;
public SoldOutState(VehicleMachine vehicleMachine) {
this.vehicleMachine = vehicleMachine;
}
@Override
public void coin() {
System.out.println("商品已经售罄");
}
@Override
public void refund() {
System.out.println("商品已经售罄");
}
@Override
public void lottery() {
System.out.println("商品已经售罄");
}
@Override
public void award() {
System.out.println("商品已经售罄");
}
}
//Context:投币机
public class VehicleMachine {
private NoMoneyState noMoneyState;
private HasMoneyState hasMoneyState;
private SolingState solingState;
private SoldOutState soldOutState;
private int goodCount = 1;
private BaseState currentState;
public VehicleMachine(int goodCount) {
noMoneyState = new NoMoneyState(this);
hasMoneyState = new HasMoneyState(this);
solingState = new SolingState(this);
soldOutState = new SoldOutState(this);
this.goodCount = Math.max(goodCount, 1);
this.currentState = noMoneyState;
}
public VehicleMachine coin() {
currentState.coin();
return this;
}
public VehicleMachine refund() {
currentState.refund();
return this;
}
public VehicleMachine lottery() {
currentState.lottery();
return this;
}
public VehicleMachine award() {
currentState.award();
return this;
}
public void setCurrentState(BaseState state){
this.currentState = state;
}
public NoMoneyState getNoMoneyState() {
return noMoneyState;
}
public HasMoneyState getHasMoneyState() {
return hasMoneyState;
}
public SolingState getSolingState() {
return solingState;
}
public SoldOutState getSoldOutState() {
return soldOutState;
}
public void setGoodCount(int count) {
this.goodCount = count;
}
public int getGoodCount() {
return goodCount;
}
public BaseState getCurrentState() {
return currentState;
}
}
运行示例
//代码运行示例
VehicleMachine vehicleMachine = new VehicleMachine(1);
vehicleMachine.coin().lottery().refund().award();
vehicleMachine.refund();
vehicleMachine.coin().refund().lottery().refund().award();
投币成功
正在出货
正在出货,请稍后
商品已领取
尚未投币,无法退款
投币成功
已经退款
尚未投币,无法抽奖
尚未投币,无法退款
尚未投币,无法领奖
评论 (0)