状态设计模式

状态设计模式


1. 简单介绍

状态模式(State)是一种行为型设计模式。当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类。简单来说就是,一个含有多种状态的实例,其行为随状态的变化而变化。

2. 使用场景
  • 当控制一个对象状态转换的条件表达式过于复杂时,采用状态模式把状态的判断逻辑转移到表示不同状态的一系列类当中,起到判断逻辑简单化的作用
3. 场景举例

电商购物时,订单的状态有非常多,如果单纯的通过if-else进行状态的判断后,进行后续操作,则代码的可维护性不高。此时可以通过状态模式,将订单的各个状态进行抽象。具体的状态下的操作,可以封装到对应的状态类型,从而将复杂的if-else判断逻辑简单化。

4. UML类图

状态设计模式_第1张图片

5. 具体实现

描述

  • 背景:网购时,订单的存在多种状态。通过状态模式,来模拟订单在不同的操作后,订单的状态变化。
  • 订单的状态:待付款(订单初始状态)、代发货、待收货、待评价、已完结
  • 订单的操作:付款(状态变为待发货)、取消订单(状态变为已完结)、发货(状态变为待收货)、收货(状态变为待评价)、评价(状态变为已完结)
  • PendingPaymentState:待付款状态类,此时可以对订单进行取消和付款
  • ToBeDeliveredState:待发货状态,订单在该状态下只能进行发货操作
  • ToBeReceivedState:待收货状态,该状态只能进行收货操作
  • CommentState:待评价状态,订单在该状态下只能进行评价操作
  • FinishedState:订单完结状态,订单无法进行任何操作
  • Client:客户端

状态转移图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ag4EdRrU-1586312336192)(./images/状态转移图.png)]

代码实现

State.java

/**
 * 状态接口,状态的变化对应其中某一个接口
 */
public interface State {

    /**
     * 付款
     */
    void payment() throws Exception;

    /**
     * 取消订单
     */
    void cancel() throws Exception;

    /**
     * 发货
     */
    void ship() throws Exception;

    /**
     * 收货
     */
    void receipt() throws Exception;

    /**
     * 评价
     */
    void evaluate() throws Exception;

    /**
     * 获取当前状态描述
     */
    String getCurrentState();
}

AbstractState.java

/**
 * 抽象状态类,起到适配作用
 */
public abstract class AbstractState implements State {

    protected Order order;

    public AbstractState(Order order) {
        this.order = order;
    }

    @Override
    public void payment() throws Exception {
        System.out.println(order.getCurrentState() + "无法进行付款操作,请先提交订单");
        throw new Exception();
    }

    @Override
    public void cancel() throws Exception {
        System.out.println(order.getCurrentState() + "无法进行取消操作");
        throw new Exception();
    }

    @Override
    public void ship() throws Exception {
        System.out.println(order.getCurrentState() + "无法进行发货操作,请先付款");
        throw new Exception();
    }

    @Override
    public void receipt() throws Exception {
        System.out.println(order.getCurrentState() + "无法进行收获操作,请先发货");
        throw new Exception();
    }

    @Override
    public void evaluate() throws Exception {
        System.out.println(order.getCurrentState() + "无法进行评价操作,请先确认收获");
        throw new Exception();
    }
}

PendingPaymentState.java

/**
 * 待付款状态类,此时可以对订单进行取消和付款
 */
public class PendingPaymentState extends AbstractState {

    public PendingPaymentState(Order order) {
        super(order);
    }

    /**
     * 订单付款后,状态转为代发货
     */
    @Override
    public void payment() throws Exception {
        order.setState(new ToBeDeliveredState(order));
    }

    /**
     * 取消订单后,状态转为已完结
     */
    @Override
    public void cancel() throws Exception {
        order.setState(new FinishedState(order));
    }

    @Override
    public String getCurrentState() {
        return StateEnum.PENDING_PAYMENT.getDesc();
    }
}

ToBeDeliveredState.java

/**
 * 待发货状态,订单在该状态下只能进行发货操作
 */  
public class ToBeDeliveredState extends AbstractState {

    public ToBeDeliveredState(Order order) {
        super(order);
    }

    /**
     * 订单进行发货操作,状态转为待收货
     */
    @Override
    public void ship() throws Exception {
        order.setState(new ToBeReceivedState(order));
    }

    @Override
    public String getCurrentState() {
        return StateEnum.TO_BE_DELIVERED.getDesc();
    }
}

ToBeReceivedState.java

/**
 * 待收货状态,该状态只能进行收货操作
 */
public class ToBeReceivedState extends AbstractState {

    public ToBeReceivedState(Order order) {
        super(order);
    }

    /**
     * 待收货状态,进行收货操作后状态变为待评价
     */
    @Override
    public void receipt() throws Exception {
        order.setState(new CommentState(order));
    }

    @Override
    public String getCurrentState() {
        return StateEnum.TO_BE_RECEIVED.getDesc();
    }
}

CommentState.java

/**
 * 待评价状态,订单在该状态下只能进行评价操作
 */
public class CommentState extends AbstractState {

    public CommentState(Order order) {
        super(order);
    }

    /**
     * 待评价状态下的订单,进行评价后,状态转为完结
     */
    @Override
    public void evaluate() throws Exception {
        order.setState(new FinishedState(order));
    }

    @Override
    public String getCurrentState() {
        return StateEnum.COMMENT.getDesc();
    }
}

FinishedState.java

/**
 * 订单完结状态,订单无法进行任何操作
 */
public class FinishedState extends AbstractState {

    public FinishedState(Order order) {
        super(order);
    }

    @Override
    public String getCurrentState() {
        return StateEnum.FINISHED.getDesc();
    }
}

Order.java

/**
 * 订单
 */
public class Order  {

    /**
     * 当前订单状态
     */
    private State state;

    /**
     * 订单初始化状态为待付款
     */
    public Order() {
        this.state = new PendingPaymentState(this);
    }
    
    // 订单付款操作
    public void payment() throws Exception {
        state.payment();
    }

    // 订单取消操作
    public void cancel() throws Exception {
        state.cancel();
    }

    // 订单发货操作
    public void ship() throws Exception {
        state.ship();
    }

    // 订单收获操作
    public void receipt() throws Exception {
        state.receipt();
    }

    // 订单评价操作
    public void evaluate() throws Exception {
        state.evaluate();
    }

    // 查看订单当前状态
    public String getCurrentState() {
        return state.getCurrentState();
    }
    // 省略Getter和Setter方法
}

StateEnum.java

/**
 * 订单状态枚举
 */
public enum StateEnum {

    /**
     * 待付款状态
     */
    PENDING_PAYMENT(1, "待付款状态"),

    TO_BE_DELIVERED(2, "待发货状态"),

    TO_BE_RECEIVED(3, "待收货状态"),

    COMMENT(1, "待评价状态"),

    FINISHED(1, "已完结状态");

    /**
     * 状态对应code码
     */
    private Integer stateCode;

    /**
     * 状态对应的描述
     */
    private String desc;

    StateEnum(Integer stateCode, String desc) {
        this.stateCode = stateCode;
        this.desc = desc;
    }

    public Integer getStateCode() {
        return stateCode;
    }

    public String getDesc() {
        return desc;
    }
}

Client.java

/**
 * 客户端
 */
public class Client {

    public static void main(String[] args) throws Exception {

        // 1. 创建订单,并查看订单状态
        Order order = new Order();
        // 1.1 输出:待付款状态
        System.out.println(order.getCurrentState());

        // 2. 进行付款操作
        order.payment();
        // 2.1 输出:待发货状态
        System.out.println(order.getCurrentState());
        // 2.2 跳过发货操作,直接进行评价操作,输出:待发货状态无法进行评价操作,请先确认收获
        // order.evaluate();

        // 3. 进行发货操作
        // 3.1 输出:待收货状态
        order.ship();
        System.out.println(order.getCurrentState());

        // 4. 确认收获
        // 4.1 输出:待评价状态
        order.receipt();
        System.out.println(order.getCurrentState());

        // 5. 订单评价
        order.evaluate();
        // 5.1 输出:已完结状态
        System.out.println(order.getCurrentState());
    }
}
7. 源码展示

你可能感兴趣的:(设计模式)