Android design pattern detailed state pattern

foreword

The behavior in the state pattern is determined by the state, and different states have different behaviors.
The structure of the state pattern and the strategy pattern are almost exactly the same, but their purpose and essence are completely different.
The behavior of the state pattern is parallel and irreplaceable, while the behavior of the strategy pattern is independent of each other and interchangeable.
The state pattern packs the behavior of the object into different state objects, and each state object has a common abstract state base class.
The intent of the state pattern is to allow an object to change its behavior when its internal state changes.

Definition: Allows the behavior of an object to change when its internal state changes, and the object appears to change its class.

scenes to be used:

  • The behavior of an object depends on its state, and it must change its behavior according to the state at runtime;
  • The code contains a large number of conditional statements related to the state of the object, such as a large number of multi-branch statements (if-else or switch-case) in an operation, and these branches depend on the state of the object;

UML class diagram:

At first glance, this is almost the same as the strategy pattern, let's take an example to see the difference between the two;

Implementation example

Let's take Weibo user status as an example. The status can be divided into login and logout status. In the login status, you can forward and comment normally, and in the login status, you will be prompted to log in. If you do not use the status mode, you need to judge the status through if-else Processing, below we use the state pattern to achieve:

  • First, define the user login state interface, UserState
interface UserState {
   //Comment
   fun comment()

   //Forward
   fun forward()
}
  • Defines login state handling, LoginState
class LoginState : UserState{
    override fun comment() {
        println("Comment on Weibo!")
    }

    override fun forward() {
        println("Forward Weibo!")
    }
}
  • Define unlogged state processing, LogoutState
class LogoutState : UserState {
    override fun comment() {
        println("Not logged in, please log in first!")
    }

    override fun forward() {
        println("Not logged in, please log in first!")
    }
}
  • Define the state management class, StateContext
class StateContext : UserState {
    /**
     * Not logged in by default
     */
    private var userState: UserState = LogoutState()

    fun setState(userState: UserState) {
        this.userState = userState
    }

    override fun comment() {
        userState.comment()
    }

    override fun forward() {
        userState.forward()
    }


}
  • call test
object Test {
    @JvmStatic
    fun main(args: Array<String>) {
        val userStateContext = StateContext()
        userStateContext.comment() //If you are not logged in by default, it will print "Not logged in, please log in first"
        userStateContext.setState(LoginState())//switch to login
        userStateContext.forward() // Print "Forward Weibo!"
    }
}

It can be seen that the states are parallel and irreplaceable, but can be converted to each other.

State pattern in Android source code

  • StateMachine class in Android WIFI state switching;
public class StateMachine {
...

    private static class SmHandler extends Handler {

      
        private HaltingState mHaltingState = new HaltingState();

        private QuittingState mQuittingState = new QuittingState();

        private StateMachine mSm;

  		//Define HaltingState
        private class HaltingState extends State {
            @Override
            public boolean processMessage(Message msg) {
                mSm.haltedProcessMessage(msg);
                return true;
            }
        }
		
		definition QuittingState
        private class QuittingState extends State {
            @Override
            public boolean processMessage(Message msg) {
                return NOT_HANDLED;
            }
        }

       
        private final State processMsg(Message msg) {
            StateInfo curStateInfo = mStateStack[mStateStackTopIndex];
            	//Call state.processMessage for processing
                while (!curStateInfo.state.processMessage(msg)) {
     
                }
            }
           
        }

        private SmHandler(Looper looper, StateMachine sm) {
            super(looper);
            mSm = sm;

            addState(mHaltingState, null);
            addState(mQuittingState, null);
        }

  

    }

....
}

Summarize

The key point of the state mode is that different states have different responses to the same behavior. In fact, it is a specific example of using polymorphism to realize the judgment statement.

advantage:
Putting all behaviors related to a specific state into a state object provides a better way to organize code related to a specific state, avoiding code bloat while ensuring scalability and maintainability.

shortcoming:
As the state increases, the number of classes and objects will inevitably increase.

epilogue

If the above article is of some help to you, I hope you will not be stingy to give it a thumbs up and follow. Every small move of yours is my unremitting motivation to keep writing! ღ( ´・ᴗ・` )

Tags: Design Pattern Android

Posted by shyonne2004 on Fri, 23 Dec 2022 21:17:11 +1030