在回答您的问题之前,我建议先回顾一下模式的概念,并对您的代码提出一些小的修改建议。
状态模式允许对象在其内部状态改变时更改其行为。
在您的情况下,空闲和清洗是很好的状态候选项,而洗衣机是承载状态对象的好选择。
不过,有三点需要注意:
1)状态提供的方法应该是一些操作,其实现根据对象所处的状态而异。
在您的声明中:
public interface WashingMachineState {
public void openLid();
public void closeLid();
public void start();
public void stop();
public void washing();
}
washing()
不是一个动作,而是一个状态。
从空闲变为洗涤状态的是 start()
动作。
在状态模式中,带有状态的对象称为上下文。
在你的情况下,上下文是 WashingMachine
。
2) 在状态模式中,思想是上下文想要执行一些行为,行为会根据当前状态进行变化。
为了实现这一点,上下文将其处理委托给其当前状态实例。
它避免了上下文中有许多if-else if(对于每个处理),还使上下文的复杂性减小,因为当您使用状态模式时,可以获得行为家族::
要执行操作,状态实例需要上下文 (WashingMachine
)。
针对这个问题,您有两种方式:
要么将 WashingMachine
对象存储为状态实例的字段,要么在上下文 WashingMachine
对象将处理委托给状态时将其作为参数传递。
我建议您使用无状态的方式。
因此,当在 WashingMachine
实例上调用 startWashing()
操作时,WashingMachine
实例应通过传递自己(例如 state.startWashing(this)
)将处理委托给 state.startWashing()
。
状态应该提供一个 WashingMachine
参数:
public interface WashingMachineState {
void openLid(WashingMachine machine);
void closeLid(WashingMachine machine);
void pushStartBtn(WashingMachine machine);
void pushStopBtn(WashingMachine machine);
}
3) 你实际上定义了两种状态:空闲和清洗。
这些状态应该增加一个 停止
状态,因为当洗衣机处于 "正在停止" 状态时,一些操作(例如打开门、按下启动按钮等)具有特定的行为。需要注意的是,仅使用两个状态,您可能还会想知道该模式是否相关。
现在我可以回答你的问题了。
我想知道从空闲到清洗之间切换状态的实现方式有两种,这是我在网上看到的:
1. WashingMachine
类实现 State 接口,并根据某些条件从空闲状态切换到清洗状态或反之亦然。
2. Idle 和 Washing 类使用 WashingMachine
作为成员变量。
WashingMachine
和 WashingMachineState
是协作但不同的东西。
所以它们不应该依赖于相同的接口。
将 WashingMachine
对象作为状态子类的字段是一种可能性。
如前所述,您也可以将 WashingMachine
作为 State 方法的参数传递。
请注意,直接执行从一个状态到另一个状态的切换不是由 WashingMachine
执行的。
这是由状态执行的。
状态应该调用 WashingMachine.changeState()
来执行它。
WashingMachine
可以是:
public class WashingMachine {
private WashingMachineState state;
public WashingMachine() {
this.state = new Idle();
}
protected void changeState(WashingMachineState state) {
this.state = state;
}
public void openLid(){
state.openLid(this);
}
public void closeLid(){
state.closeLid(this);
}
public void pushStartBtn(){
state.pushStartBtn(this);
}
public void pushStopBtn(){
state.pushStopBtn(this);
}
public State getState() {
return state;
}
}
关于WashingMachine
的修改解释:
关于从空闲状态切换到洗涤状态,我认为只有在IdleState
状态下调用pushStartBtn()
时才可能发生。
以下是示例:
public class IdleState implements State {
public void openLid(WashingMachine machine){
...
}
public void closeLid(WashingMachine machine){
...
}
public void pushStartBtn(WashingMachine machine){
...
machine.changeState(new WashingState());
}
public void pushStopBtn(WashingMachine machine){
...
}
}