Before addressing your question, I prefer to reconsider the idea of โโthe template and offer you some small changes in your code.
A state template allows an object to change its behavior when its internal state changes.
In your case, Idle and Washing are good candidates for states, and WashingMachine are good candidates for transferring a state object.
However, three points:
1) The methods provided by the states must be some actions, the implementation of which differs depending on the state of the object.
In your statement:
public interface WashingMachineState { public void openLid(); public void closeLid(); public void start(); public void stop(); public void washing(); }
washing() is not an action, but a state.
This is the start() action, which changes state from downtime to washing.
In a state template, an object with a state is called a context .
In your case, the context is WashingMachine .
2) in the state template, the idea is that the context wants to perform some actions whose behavior changes in accordance with the current state.
To do this, the context delegates its processes to its current state instance.
This avoids the use of if-else if in the context (for each processing), and also reduces the complexity of the context, because when you use the state template, you get families of behavior models:
To perform actions, state instances need context ( WashingMachine ).
To solve this issue, you have two ways to do it:
Either save the WashingMachine object as a field in the state instance, or pass it as an argument when the WashingMachine context WashingMachine passes processing to the state.
I suggest you use a stateless method.
So, when the startWashing() operation is called on the WashingMachine instance, the WashingMachine instance must delegate the processing of state.startWashing() , passing itself, for example, state.startWashing(this) .
The state should indicate as a WashingMachine parameter:
public interface WashingMachineState { void openLid(WashingMachine machine); void closeLid(WashingMachine machine); void pushStartBtn(WashingMachine machine); void pushStopBtn(WashingMachine machine); }
3) In fact, you have identified two conditions: downtime and washing.
They must be filled with the stopping state, because some operations on the machine (opening a door, pressing the start of btn, for example ...) have a certain behavior when the machine is in the "stopped" state.
Note that with only two states, you may also be wondering if the template is suitable.
Now I can answer your question.
I want to know when, between the state between idle and washing, the implementation can be in two ways that are viewed through the network
1. The WashingMachine class implements the state of the interface and the state of switching from Idle to washing or vice versa based on some condition
2. The idle and the wash class have WashingMachine as a member variable.
WashingMachine and WashingMachineState work together, but different things.
Therefore, they should not rely on the same interface.
Adding a WashingMachine object as fields of state subclasses is an option.
As explained, you can also pass the WashingMachine parameter as a parameter of State methods.
Please note that WashingMachine does not directly transition from state to state.
This is done by the state. And the states must call WashingMachine.changeState() to execute it.
WashingMachine can be:
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; } }
Explanations about modifications to WashingMachine :
changeState more significant as setState when using a state template.
changeState(State) can use the protected modifier to reduce the visibility of this method, and, of course, state subclasses must be in the same package than WashingMachine . This is an implementation detail included in Java. With other OOP languages, you have other options, of course.
On switching from downtime to washing, I think it should be possible only in the IdleState state when calling pushStartBtn() .
Here is an example:
public class IdleState implements State { public void openLid(WashingMachine machine){ ... } public void closeLid(WashingMachine machine){ ... } public void pushStartBtn(WashingMachine machine){