Builder

如何使用

import com.google.common.base.Preconditions;
import org.apache.commons.lang.StringUtils;

public class User {
    private String name; // 必填字段
    private String telephone; // 必填字段
    private String sex; // 必填字段
    private int age; // 可选字段
    private String address; // 可选字段

    private User(UserBuilder builder) {
        this.name = builder.name;
        this.telephone = builder.telephone;
        this.sex = builder.sex;
        this.age = builder.age;
        this.address = builder.address;
    }

    @Override
    public String toString() {
      return "{\"name\":" + name + ",\"telephone\":\"" + telephone
                + "\",\"sex\":\"" + sex + "\",\"age\":\""
                + age + "\",\"address\":" + address + "}";
    }

    public static class UserBuilder {
        private String name;
        private String telephone;
        private String sex;
        private int age;
        private String address;

        public UserBuilder setName(String name) {
            this.name = name;
            return this;
        }

        public UserBuilder setTelephone(String telephone) {
            this.telephone = telephone;
            return this;
        }

        public UserBuilder setSex(String sex) {
            this.sex = sex;
            return this;
        }

        public UserBuilder setAge(int age) {
            this.age = age;
            return this;
        }

        public UserBuilder setAddress(String address) {
            this.address = address;
            return this;
        }

        public User build() {
            // 必填字段校验
            Preconditions.checkArgument(StringUtils.isNotBlank(name), "name can not be empty");
            Preconditions.checkArgument(StringUtils.isNotBlank(telephone), "name can not be empty");
            Preconditions.checkArgument(StringUtils.isNotBlank(telephone), "name can not be empty");
            // 传入builder对象以构建user对象
            User user = new User(this);
            System.out.println("通过Builder模式成功构建User对象");
            return user;
        }
    }
}

public static void main(String[] args) {
    User user = new User.UserBuilder()
            .setName("张三")
            .setTelephone("18812546788")
            .setSex("男")
            .setAge(31)
            .build();
    System.out.println("通过Builder模式构建的User对象: " + user);
}

状态机

什么是状态机?

状态机(State Machine)是一种数学模型,用于描述系统在不同状态间的转换。它由以下部分组成:

状态(State):系统可能处于的各个状态。

事件(Event):触发状态转换的动作或条件。

转换(Transition):事件触发后,系统从一个状态转移到另一个状态的过程。

动作(Action):状态转换时执行的操作。

状态机分为有限状态机(FSM)和无限状态机,Spring Boot 中常用的是有限状态机。

状态机在订单管理中的应用

在商城系统中,订单状态通常包括:待支付、已支付、已发货、已收货、已完成、已取消等。状态机可以清晰地管理这些状态及其转换。

状态机基本结构与使用

StateMachine和State关系是双向的,这是因为状态机需要持有状态对象来表示当前状态,以及通过当前的状态对象中的方法进行状态的流转,而流转的结果需要重新set到状态机中,又要求State必须持有状态机对象。

当然,这里State对StateMachine的关系也可以通过依赖来表示。

定义状态机状态枚举

import lombok.Getter;

@Getter
public enum OrderStateEnum {
    WAIT_PAYMENT(1, "待支付"),
    WAIT_DELIVER(2, "待发货"),
    WAIT_RECEIVE(3, "待收货"),
    RECEIVED(4, "已收货"),
    CANCEL(5, "已取消");

    private final int state;
    private final String desc;

    OrderStateEnum(int state, String desc) {
        this.state = state;
        this.desc = desc;
    }

    public int getState() {
        return state;
    }

    public String getDesc() {
        return desc;
    }
}

事件接口定义

public interface OrderState {

    OrderStateEnum orderStateType();
    
    default void pay(OrderStateMachine stateMachine) {
        System.out.println("|--当前订单状态不支持支付,已忽略");
    }
    default void cancel(OrderStateMachine stateMachine) {
        System.out.println("|--当前订单状态不支持取消,已忽略");
    }
    default void deliver(OrderStateMachine stateMachine) {
        System.out.println("|--当前订单状态不支持发货,已忽略");
    }
    default void receive(OrderStateMachine stateMachine) {
        System.out.println("|--当前订单状态不支持收货,已忽略");
    }
}

default的作用是不需要类再重写这个方法,接口可以实现不能跳转状态的逻辑

如果当前状态能触发对应事件则重写对应方法并添加相关执行逻辑

例如:待支付状态可以有两个事件:支付或者取消

public class WaitPaymentState implements OrderState {

    @Override
    public OrderStateEnum orderStateType() {
        return OrderStateEnum.WAIT_PAYMENT;
    }

    @Override
    public void pay(OrderStateMachine stateMachine) {
        stateMachine.setCurrentState(new WaitDeliverState());
    }

    @Override
    public void cancel(OrderStateMachine stateMachine) {
        stateMachine.setCurrentState(new CancelState());
    }
}

状态机定义

缓存所有的状态映射,由当前状态对象来触发相关事件

public class OrderStateMachine {

    public static final Map<OrderStateEnum, OrderState> ORDER_STATE_MAP = new HashMap<>();

    static {
        ORDER_STATE_MAP.put(OrderStateEnum.WAIT_PAYMENT, new WaitPaymentState());
        ORDER_STATE_MAP.put(OrderStateEnum.WAIT_DELIVER, new WaitDeliverState());
        ORDER_STATE_MAP.put(OrderStateEnum.WAIT_RECEIVE, new WaitReceiveState());
        ORDER_STATE_MAP.put(OrderStateEnum.RECEIVED, new ReceivedState());
        ORDER_STATE_MAP.put(OrderStateEnum.CANCEL, new CancelState());
    }

    private OrderState currentState;

    public OrderStateMachine(OrderStateEnum orderStateEnum) {
        this.currentState = ORDER_STATE_MAP.get(orderStateEnum);
    }

    public OrderState getCurrentState() {
        return currentState;
    }

    public void setCurrentState(OrderState currentState) {
        this.currentState = currentState;
    }

    void pay() {
        currentState.pay(this);
    }

    void deliver() {
        currentState.deliver(this);
    }

    void receive() {
        currentState.receive(this);
    }

    void cancel() {
        currentState.cancel(this);
    }

}

测试

public class OrderService {

    public static void main(String[] args) {
        OrderStateMachine stateMachine = new OrderStateMachine(OrderStateEnum.WAIT_DELIVER);

        invoke(stateMachine::pay, "用户支付", stateMachine);
        invoke(stateMachine::deliver, "商家发货", stateMachine);
        invoke(stateMachine::receive, "用户收货", stateMachine);
        invoke(stateMachine::cancel, "取消支付", stateMachine);
    }

    public static void invoke(Runnable runnable, String desc, OrderStateMachine stateMachine) {
        System.out.println(desc + "前订单状态: " + stateMachine.getCurrentState().orderStateType().getDesc());
        runnable.run();
        System.out.println(desc + "后订单状态: " + stateMachine.getCurrentState().orderStateType().getDesc());
        System.out.println("------------------");
    }
}

springboot使用状态机

定义状态和事件

public enum OrderStates {
    PENDING_PAYMENT, PAID, SHIPPED, RECEIVED, COMPLETED, CANCELLED
}

public enum OrderEvents {
    PAY, SHIP, RECEIVE, COMPLETE, CANCEL
}

配置状态机-状态以及触发事件之间的关系

@Configuration
@EnableStateMachine
public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<OrderStates, OrderEvents> {

    @Override
    public void configure(StateMachineStateConfigurer<OrderStates, OrderEvents> states) throws Exception {
        states
            .withStates()
            .initial(OrderStates.PENDING_PAYMENT)
            .states(EnumSet.allOf(OrderStates.class));
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<OrderStates, OrderEvents> transitions) throws Exception {
        transitions
            .withExternal()
                .source(OrderStates.PENDING_PAYMENT).target(OrderStates.PAID).event(OrderEvents.PAY)
            .and()
            .withExternal()
                .source(OrderStates.PAID).target(OrderStates.SHIPPED).event(OrderEvents.SHIP)
            .and()
            .withExternal()
                .source(OrderStates.SHIPPED).target(OrderStates.RECEIVED).event(OrderEvents.RECEIVE)
            .and()
            .withExternal()
                .source(OrderStates.RECEIVED).target(OrderStates.COMPLETED).event(OrderEvents.COMPLETE)
            .and()
            .withExternal()
                .source(OrderStates.PENDING_PAYMENT).target(OrderStates.CANCELLED).event(OrderEvents.CANCEL)
            .and()
            .withExternal()
                .source(OrderStates.PAID).target(OrderStates.CANCELLED).event(OrderEvents.CANCEL);
    }
}

使用状态机

@Service
public class OrderService {

    @Autowired
    private StateMachine<OrderStates, OrderEvents> stateMachine;

    public void payOrder() {
        stateMachine.sendEvent(OrderEvents.PAY);
    }

    public void shipOrder() {
        stateMachine.sendEvent(OrderEvents.SHIP);
    }

    public void receiveOrder() {
        stateMachine.sendEvent(OrderEvents.RECEIVE);
    }

    public void completeOrder() {
        stateMachine.sendEvent(OrderEvents.COMPLETE);
    }

    public void cancelOrder() {
        stateMachine.sendEvent(OrderEvents.CANCEL);
    }
}

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐