我正在学习java的设计模式。
我正在做一些链接,我正试着设计一台按状态排列的洗衣机
我对状态设计模式的实现有一个疑问。
public interface State {
public void openLid();
public void closeLid();
public void start();
public void stop();
public void washing();
}
public class Idle implements State{
//implementing overidden methods
.......
}
public class Washing implements State {
//implementing overidden methods
.......
}
public class WashingMachine {
State state;
public WashingMachine(State state) {
this.state = new Idle();
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
}我想知道当在空闲状态之间切换到清洗实现时,可以通过网络看到两种方式。
1.WashingMachine类实现了状态接口,并根据某些条件将状态从Idle切换到,反之亦然。
2.以WashingMachine为成员变量的Idle和洗涤类。
请任何一个人都可以建议我有点困惑的执行部分。
发布于 2016-10-29 12:28:49
在回答您的问题之前,我更愿意回顾一下模式的概念,并建议您对代码进行一些小小的修改。
状态模式允许对象在其内部状态发生变化时更改其行为。
在您的例子中,空闲和洗涤是很好的候选状态,而WashingMachine是承载状态对象的好候选人。
然而,有三点意见:
( 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 (对于每个处理),并且它还允许降低上下文的复杂性,因为当您使用状态模式时,您会得到一系列行为:
IdleState类中。WashingState类中。要执行这些操作,状态实例需要上下文(WashingMachine)。
为了解决这个问题,你有两种方法:
或者将WashingMachine对象存储为状态实例中的字段,或者在上下文WashingMachine对象将处理委托给状态时将其作为参数传递。
我建议你用无状态的方式。
因此,当对startWashing()实例调用WashingMachine操作时,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)实际上,您定义了两种状态:空闲状态和洗涤状态。
应该使用stopping状态来完成这些操作,因为机器上的某些操作(打开门,推动启动btn )当机器处于“正停止”状态时,有一个特定的行为。
注意,在只有两种状态的情况下,您可能还想知道模式是否相关。
现在我可以回答你的问题了。
我想知道当在空闲状态之间切换到清洗实现时,可以通过网络看到两种方式。 1.
WashingMachine类在一定条件下实现状态接口,并将状态从空闲切换到清洗或切换。 2.空闲和清洗类以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的说明:
changeState作为setState更有意义。changeState(State)可以使用protected修饰符来降低该方法的可见性,当然状态子类应该在与WashingMachine相同的包中。这是一个在Java中启用的实现细节。当然,对于其他OOP语言,您还有其他选择。关于从空闲切换到清洗,我认为只有在调用IdleState状态时才有可能调用pushStartBtn()。
以下是一个例子:
public class IdleState implements State {
public void openLid(WashingMachine machine){
...
}
public void closeLid(WashingMachine machine){
...
}
public void pushStartBtn(WashingMachine machine){
//do processing with machine to begin effectively the washing
...
machine.changeState(new WashingState());
}
public void pushStopBtn(WashingMachine machine){
...
}
} 发布于 2016-10-29 10:48:28
我认为更好的选择是
public enum State{IDLE,WASHING};然后用这个。这个enum甚至可以被命名为WashingMachineState,因为您提到的状态仅指定给洗衣机--它们不会被重用,所以这里没有接口。
如果您希望在不同的设备之间共享相同的状态,例如。WashingMachine和DishWasher然后你可以用
public interface Statefull{
public State getState();
public void changeState(State newState);
}并让WashingMachine和DishWasher实现Statefull接口。使用Java 8的默认接口实现,您甚至可以在接口中包括getter实现,这样在实现类中就没有样板代码。
发布于 2016-10-29 10:47:41
好吧,让我们谈谈你的两个想法:
1.)洗衣机是个状态吗?不,绝对不是。那么它为什么需要实现状态接口呢?
2.)这几乎是可行的,但它使状态不可重用(对于这样的小型实现来说,这样的实现并不坏,但是对于像游戏这样的东西,它是很糟糕的)。它们只能是洗衣机的状态。如果我想用这些州做洗碗机呢?
你应该做的是:
创建一个接口或类,类似于StateManager,并使WashingMachine实现这个功能,然后在状态中创建一个StateManager字段,而不是使用一个具体的类。
示例:
public abstract class StateManager {
public State state;
public void setState(State newState) {
state = newState;
newState.parent = this;
}
public State getState() {
return state;
}
}状态:
public abstract class State {
public StateManager parent;
// Whenever you want to set the object's state, use this
}国家实例:
public class WashingState extends State {
// your methods here
}状态管理器示例:
public class WashingMachine extends StateManager {
// your methods here.
}我更改了所有zo类,而不是接口,因为它们使创建某些对象更容易(比如,如果您想要制造洗碗机和洗衣机,那么您可以从它们中提取洗涤部分,并为其创建一个单独的类)。
https://stackoverflow.com/questions/40318196
复制相似问题