Java state template

I am learning a design pattern in java

I worked on some links. I am trying to create a washing machine according to a state template

I have a request regarding the implementation of the state design template

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; } } 

I want to know when switching between a state between idle and erasing an implementation, there can be two ways that are viewed through the network

1. The erase class implements the State and switching state interface from Idle to wash or vice versa based on some condition

2. Idle and Laundry class has a washing machine as a member variable.

Please, anyone can assume that I'm a little confused about the implementation part.

+5
source share
3 answers

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:

  • the behavior when we are in the idle state is in the IdleState class.

  • the behavior when we are in the washing state is in the class WashingState .

  • and so on...

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){ //do processing with machine to begin effectively the washing ... machine.changeState(new WashingState()); } public void pushStopBtn(WashingMachine machine){ ... } } 
+3
source

I think the best choice would be to create

 public enum State{IDLE,WASHING}; 

and use it. This enum can even be called WashingMachineState , since the states you indicated are only for the washing machine - they will not be reused, so there are no interface points here.

If you want to use the same states between different devices, for example. WashingMachine and DishWasher , then you can use

 public interface Statefull{ public State getState(); public void changeState(State newState); } 

And let WashingMachine and DishWasher implement the Statefull interface. With the default implementation of the Java 8 interface, you could even include the getter implementation in the interface so that there is no code template when implementing the classes.

+1
source

Ok, let go of both of your ideas:

1.) What is the condition of the washing machine? No, definitely not. Then why does he need to implement a state interface?

2.) It almost works, but it makes the states not reusable (which is not bad for a small implementation like this, but for something like a game this is terrible). They can only be washing machine conditions. What if I want to use these conditions for a dishwasher?

What you should do:

Create an interface or class, something like StateManager, and make the washing machine implemented, and then instead of using a specific class, create a StateManager field in the states.

Example:

 public abstract class StateManager { public State state; public void setState(State newState) { state = newState; newState.parent = this; } public State getState() { return state; } } 

Condition:

 public abstract class State { public StateManager parent; // Whenever you want to set the object state, use this } 

Status example:

 public class WashingState extends State { // your methods here } 

An example of a state manager:

 public class WashingMachine extends StateManager { // your methods here. } 

I changed all the zo classes instead of the interface, because they simplify the creation of some objects (for example, if you want to make a dishwasher and a washing machine, then you can extract the washing part from them and make a separate class for it)

0
source

Source: https://habr.com/ru/post/1258972/


All Articles