Today, I am talking about the design mode of “state mode”, because the business encountered an order state that was extremely difficult to maintain, so I had to reconstruct it.

One of the provisions of ali’s statute reads:

Simply put, the state mode is used to eliminate a large number of redundant “if else” judgments.

For example

The business has an order table with about a dozen of the following order states, which we maintain in an enumerated type.

Next, we have a service for flow state:

Public interface OrderService {@param order * @return */ Boolean refund(order order); * @param order * @return */ Boolean cancle(order order); }Copy the code

Then his implementation class looks like this:

@Service public class OrderServiceImpl implements OrderService { @Override public boolean refund(Order order) { boolean flag = true; / / the current order status if (order. GetOrderState () = = OrderState. WAITSHIP, getCode () | | order. GetOrderState () = = OrderState. PAYED. GetCode ()) {/ / if it is paid, momentum goods, direct order. REFUND success setOrderState (OrderState. REFUND. GetCode ()); }else if (order.getOrderState() == OrderState.ALREADYSHIP.getCode() || order.getOrderState() == OrderState. ENDED. GetCode ()) {/ / if it is already shipped or deal finished, transfer to a refund, waiting for the merchants to audit the order. The setOrderState (OrderState. REFUNDING. GetCode ()); }else {// All other states are abnormal, reject the flow flag = false; } return flag; } @Override public boolean cancle(Order order) { boolean flag = true; / / determine the current state of the if (order. GetOrderState () = = OrderState. NOTPAY. GetCode ()) {/ / unpaid state can only cancel the order order.setOrderState(OrderState.CANCELED.getCode()); }else { flag = false; } return flag; }}Copy the code

A simple refund flow requires at least as much “if else” judgment as the one above. The following cancle flow is a little simpler.

Here, too, I have simplified some of the code, which is actually more complex, but fortunately the dependency between states is not so strong that there are no nested layers of “if else” judgments. How to change the state mode?

The state pattern

The reason why there are a lot of “if else” judgments in the traditional judgment mode is that we do not know what state the current order is in, so we need to judge how the current order should flow in different states.

Step 1: Create an abstract state base class that defines all state flow operations. I only wrote two of them here.

@slf4j public Abstract class AbstOrderState {** * * @param order * @return */ public Boolean refund(order order){log.info(" can't get a refund from status: {} ",getState()); return false; } @param order @return */ public Boolean cancle(order order){log.info(" " {} go to cancel state ",getState()); return false; } @return */ public abstract String getState(); }Copy the code

Second, create a corresponding state class for each state and integrate the abstract state base class

The third step is to realize the concerned flow operation in each state respectively. We give examples of the realization of two state subclasses.

This is the paid state

Public class PayEdState extends AbstOrderState {@override public Boolean refund(Order Order){ Target state is a REFUND for the order. SetOrderState (OrderState. REFUND. GetCode ()); return true; } // The current state is paid, the target state is cancelled, unable to flow, abnormal state // no need to rewrite, use the abstract base class default implementation, Public Boolean cancle(Order Order){// return false; // } @Override public String getState(){ return OrderState.PAYED.getDesc(); }}Copy the code

This is the unpaid state

Public class NotPayState extends AbstOrderState {@override public Boolean refund(Order Order){ Return true; } @override public Boolean cancle(Order Order){return true; } @Override public String getState() { return OrderState.NOTPAY.getDesc(); }}Copy the code

Step 4, how to use

@Test
    public void test(){
        //初始化一个订单,默认未支付状态
        Order order = new Order();
        order.setOrderState(OrderState.NOTPAY.getCode());

        //我想退款
        AbstOrderState state = OrderState.getStateByCode(order.getOrderState());
        if (state.refund(order)){
            log.info("ok");
        }else {
            log.info("failed");
        }
    }
Copy the code

At this point, the state mode is done. In fact, if you are careful, you will notice that there is no “if else” line in the state mode, but the disadvantage is that there are many more classes, but this is the inevitable result of abstractness.

Compare the

The example of actual order state is not a perfect fit for the state pattern because the dependencies between states are less strong and nesting judgments are less likely, but the effect is clear.

Just think about it, if I add a state called “frozen state” to my order in the future, I just need to create a new state class and only care about the flow operation related to the frozen state. I just need to rewrite it without going to the previous logic to change and change.

State mode is a very good design mode, we recommend you to use it in the project, in addition to the initial coding trouble, the subsequent maintenance and expansion is really almost zero cost.

In the near future, we will compile a series of design patterns, which will talk about 23 design patterns. If you are interested, please follow them


Focus on the public not getting lost, a programmer who loves to share.
Public number reply “1024” add the author wechat together to discuss learning!
The public account replies “interview questions” to send you a copy of interview questions and the author’s answers
All the case code materials used in each article are uploaded to my personal Github
Github.com/SingleYam/o…
Welcome to step on it!