This is the 8th day of my participation in the August More Text Challenge. For details, see:August is more challenging

Welcome to today’s class, where we’re going to look at the —- status mode that you may not hear about, but you can use anywhere. This month, I will talk about Java design patterns in detail. Please click on the profile picture and follow my column. I will keep updating.

Series of articles:

Singletons of design patterns

The factory model of design pattern

The builder pattern of design patterns

Proxy patterns of design patterns

The visitor pattern of design patterns

Adaptor patterns for design patterns

The designer mode of the design mode

. Under continuous update

Without further ado, let’s get to the point

The state pattern

As the name implies, the application scenario must be to change the state of an event business at any time, such as the order we paid, we bought the goods until the user received the goods, can use the state mode.

Its original definition was to allow an object to change its behavior when its internal state changes, as if the object were modifying its own class.

Simply put, a state pattern allows an object to control changes in behavior by defining a series of state changes, such as online purchases. Define several package delivery states for purchased items, ordered, in transit, signed, and other state adjustments, that is, when the package state changes, the corresponding external operations will be triggered.

Let’s look at the picture below. Something like this (this image is from the Internet) :

From the figure, we can see that the state pattern contains three key actors:

  • Context: A class that stores the current state and provides an operation to update the state. (Usually you see the Context word Context information class, spring has a lot of that)

  • An abstract State class: can be an interface or an abstract class that defines the operational methods that declare State updates

  • Concrete state classes (StateA, etc.) : Methods that implement the definition of abstract state classes, specifying the code implementation logic that corresponds to the state change according to the specific scenario

Next, we take the actual scenario of payment order state and combine it with the code to get a deeper understanding of the state pattern

The code shown

To help you understand how state patterns work, let’s use a simple example. In the process of payment for an order by the user, when we select the goods and submit the order, the user clicks to pay, pulls up to pay, and finally succeeds in payment. Here we define four simple order states: Order created, Payment in progress, Payment cancelled, and payment successful. As shown in the figure below:

In view of the diagram above, we use the state pattern code to implement the business

First, we define the OrderState, OrderState, and declare an updateState() method in the interface to update the state, which takes the OrderContext information class OrderContext as a parameter.

// Define the order status interface
public interface OrderState {
    
    /** * defines 4 states * 1 - create order * 2 - order payment * 3 - User cancel payment * 4 - payment successful *@param ctx
     */
    void updateState(OrderContext ctx);
}
Copy the code

We will then define the context information class orderContext in detail, which contains an OrderState and an order number (orderNo).

public class OrderContext {
    private OrderState currentState; // Order status
    private String orderNo; // Order number
    
    public OrderContext(OrderState currentState, String orderNo) {
        this.currentState = currentState;
        this.orderNo = orderNo;
        // The default initialization creates the order
        if(currentState == null) {
            this.currentState = Acknowledged.instance(); }}public OrderState getCurrentState(a) {
        return currentState;
    }
    public void setCurrentState(OrderState currentState) {
        this.currentState = currentState;
    }
    public String getOrderNo(a) {
        return orderNo;
    }
    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }
    
    // Start modifying the state (information carried by the current object)
    public void update(a) {
        currentState.updateState(this); }}Copy the code

Next, we define the specific status classes in turn: CreateOrder (CreateOrder), pay order (OrderProcessing), CancelOrder (CancelOrder), and pay success (OrderPaySuccess). Each class implements the updateState() method, while using the singleton pattern to simulate the uniqueness of the state.

// Create the order
public class CreateOrder implements OrderState {

    //Singleton
    private static CreateOrder instance = new CreateOrder();
    private CreateOrder(a) {}
    public static CreateOrder instance(a) {
        return instance;
    }

    @Override
    public void updateState(OrderContext ctx) {
        System.out.println("->. -> Start creating order");
        
        // After creating the order, change the order to...... in order paymentctx.setCurrentState(OrderProcessing.instance()); }}// The order is being paid
public class OrderProcessing implements OrderState  {

    //Singleton
    private static OrderProcessing instance = new OrderProcessing();
    private OrderProcessing(a) {}
    public static OrderProcessing instance(a) {
        return instance;
    }

    @Override
    public void updateState(OrderContext ctx) {
        System.out.println("-- > -- > Order payment in progress");
        
        // Then change to payment success (not considering user cancel midway)ctx.setCurrentState(InTransition.instance()); }}// The order was paid successfully
public class OrderPaySuccess implements OrderState  {

    //Singleton
    private static OrderPaySuccess instance = new OrderPaySuccess();
    private OrderPaySuccess(a) {}
    public static OrderPaySuccess instance(a) {
        return instance;
    }

    @Override
    public void updateState(OrderContext ctx) {
        System.out.println("-- > -- > user paid successfully end"); }}Copy the code

Finally, we run a unit test that changes the state by performing an update to the context information class.

public class Client {
    public static void main(String[] args) {
        OrderContext ctx = new OrderContext(null."123456789"); ctx.update(); ctx.update(); }}/ / output->. -> Start to create order -> -> Order payment -> -> user payment success endCopy the code

OK, so that’s the end of our code section. One might ask why the state mode is used, but there are two main reasons:

  • First, reduce coupling. When the business to be designed has complex state transitions, we expect state changes to enable rapid change operations and reduce code coupling.

  • The second is to avoid adding complexity to the code that would otherwise fill the screen with if eles

conclusion

Another example that strikes you as even easier to understand is the five states of a thread pool: there are five states in the lifetime of a thread, and only after the current state is obtained can the next state be determined.

Whatever you get, you get what you want. That’s true of any pattern. Let’s think about the disadvantages of state patterns. This will help us to better optimize the code in the future:

  • Creates a lot of discrete classes. State patterns increase the number of system classes and objects by defining a specific state class for each state

  • The more complex the state switching relationship is, the more difficult the code implementation is. If the services are extremely complex and time-consuming, the asynchronous mode is not recommended.

  • Do not meet the open closed original, if you want to change the logic, such as to move the specific inside the business code.

OK, that’s enough for status mode today!

overtones

Thank you for reading, and if you feel you’ve learned something, please like it and follow it.

I have included this chapter in my project, click on the project below, and follow the column. I will publish dry items every day, and I will continue to enter design patterns this month.

Come on! See you next time!