This is the 7th day of my participation in Gwen Challenge

The business scenario

Those of you who have studied design patterns often wonder when you are writing code, when will you use your prehistorical powers?

Recently, I happened to meet the most appropriate demand, a brief introduction:

  • You need to monitor the device at all times
  • You can send up move/down move/stop move instructions to the device
  • When the device is offline, it needs to be reconnected and initialized
  • During device initialization, obtain device information
  • You need to obtain device coordinates when the device is running properly

plan

Following the above requirements, we can easily write code with the following structure:

if (device.getStatus() == Device.Status.OFFLINE) {
    // Business code
} else if (device.getStatus() == Device.Status.INIT) {
    // Business code}...Copy the code

At first glance, the logic is pretty rigorous, but the reality is that when you move up, you get this bunch of ifs, and it also happens when you move down, when you stop moving

At this point, we should use state mode

When a bunch of identical if statements occur in two or more different methods, we should consider replacing them with State

The difference between state mode and policy mode is that in state mode users cannot perceive and participate in state changes of objects, while in policy mode they can

Write state classes

First, create a BaseState class, basestate.java:

public abstract class BaseState {

    Device device;
    
    protected BaseState(Device device) {
        this.device = device;
    }
    
    /** * Heartbeat link */
   public abstract void heartBeat(a);

}
Copy the code

Continue to create an OffLineState inherited from the base state, offlinestate.java:

public class OffLineState extends BaseState {

    public OffLineState(Device device) {
        super(device);
    }
    
    @Override
    public void heartBeat(a) {
        homing();
    }
    
    public void homing(a) {
        try {
            device.homing();
            device.setState(new InitState(device));
        } catch (IOException e) {
            device.setState(newOffLineState(device)); }}}Copy the code

As you can see, the change in state is internal and is not perceived by the user

Next create the initialization class, initstate.java:

public class InitState extends BaseState {

    public InitState(Device device) {
        super(device);
    }

    @Override
    public void heartBeat(a) {
        try {
            if (device.isMove()) {
                return;
            }
            device.setZeroPosition(device.currentPosition());
            device.setState(new OnLineState(device));
        } catch (IOException e) {
            device.setState(newOffLineState(device)); }}}Copy the code

Replace method

Next, we just need to replace the code device.heartbeat () with device.getState().heartbeat () in the actual business logic

I will not repeat the details here, but simply show the author’s business-related codes:

public class Connector {

    private static final int INTERVAL = 2000;

    @Async
    public void connect(Device device) {
        try {
            while(true) { device.getState().heartBeat(); Thread.sleep(INTERVAL); }}catch(InterruptedException e) { Thread.currentThread().interrupt(); }}}Copy the code

conclusion

Finally, summarize the characteristics of state mode:

  1. State classes have the same public methods
  2. The state class has an attribute pointing to the entity class that uses the state
  3. The status class automatically switches the status internally, and users cannot sense it
  4. Used to replace large recurring if statements