语法糖甜不甜?巧用枚举实现“状态”转换限制 (2)

并提供了 values()valueOf(String name) 的静态方法。

我们定义的枚举变量实际上是编译器帮我们自动生成了构造函数。

所有枚举类都是 Enum 的子类,枚举类可以实现一个或多个接口。

Enum

Enum 是所有 Java 语言枚举类型的公共基类,实现了 Comparable 和 Serializable 接口。它包含 final 类型的 name 和 ordinal (此枚举常量的序号,从0开始)属性,下面我们来了解下它的方法

protected Enum(String name, int ordinal);——构造方法;

public String toString();——返回 name 字段,即枚举定义枚举变量的字符串;

protected final Object clone();——抛出 CloneNotSupportedException 异常,保证枚举类永远不会被克隆;

public final Class getDeclaringClass();——返回与此枚举常量的枚举类型对应的类对象;

protected final void finalize();—— 枚举类不能有 finalize 方法;

readObject(ObjectInputStream in);& readObjectNoData();—— 抛出InvalidObjectException 异常,防止默认反序列化;

扩展

枚举类中可以自定义属性

自定义的属性值最好用 private final 修饰,防止生成的 set 方法在使用时修改属性值,使代码更加安全。

枚举类中可以自定义构造函数

构造函数必须为 private 修饰,防止在别处声明此类对象。

枚举类可以自定义方法,枚举项可以选择性覆盖自定义的方法。

public enum OrderStatus{
    NO_PAY("未支付",0),
    PAY("已支付",1){
        @Override
        public void printOrderStatus() {
            System.out.println("已支付");
        }
    },
    REFUNDING("退款中",2),
    REFUNDED("退款成功",3),
    FAIL_REFUNDED("退款失败",4),
    ;

    private final String name;
    private final int status;

    private OrderStatus(String name,int status){
        this.name = name;
        this.status = status;
    }

    public void printOrderStatus(){
        System.out.println("打印订单状态");
    }
}


public class EnumTest {
    public static void main(String[] args) {
        OrderStatus.PAY.printOrderStatus();
        OrderStatus.NO_PAY.printOrderStatus();
    }
}

语法糖甜不甜?巧用枚举实现“状态”转换限制

枚举类也可以有抽象方法,但是枚举项必须重写该方法。

枚举类实现接口

与普通类一样,实现接口的时候需要实现接口的抽象方法,也可以让枚举类的不同对象实现不同的行为。

//定义一个接口
public interface Order {
    void printOrderStatus();
}

//枚举类实现该接口
public enum OrderStatus implements Order{
    NO_PAY("未支付",0){
        @Override
        public void printOrderStatus() {
            System.out.println("未支付");
        }
    },
    PAY("已支付",1){
        @Override
        public void printOrderStatus() {
            System.out.println("已支付");
        }
    },
    REFUNDING("退款中",2){
        @Override
        public void printOrderStatus() {
            System.out.println("退款中");
        }
    },
    REFUNDED("退款成功",3){
        @Override
        public void printOrderStatus() {
            System.out.println("退款成功");
        }
    },
    FAIL_REFUNDED("退款失败",4){
        @Override
        public void printOrderStatus() {
            System.out.println("退款失败");
        }
    },
    ;

    private final String name;
    private final int status;

    private OrderStatus(String name,int status){
        this.name = name;
        this.status = status;
    }
}

此时查看编译后的文件,会发现除了生成 OrderStatus.class 文件之外,还生成了多个 .class 文件:

语法糖甜不甜?巧用枚举实现“状态”转换限制

它们是 OrderStatus.class 中生成的匿名内部类的文件。

状态转换 需求

订单是电商项目中不可缺少的组成部分,而订单状态的转换也是我们经常讨论的问题。我们都知道订单状态的转换是有一定的逻辑性的,不可以随意转换。

:你想购买某个商品,只是把它加入了购物车,此时应该是未支付状态。如果来个请求想把它转换为退款状态,那么系统应该抛出提示信息“状态转换失败,请先完成购买!”

接下来我们就用枚举来完成一下订单状态转换的限制。

实现

枚举类定义:

public enum OrderStatus{
    NO_PAY("未支付",0){
        @Override
        public Boolean canChange(OrderStatus orderStatus) {
            switch (orderStatus){
                case PAY:
                    return true;
                default:
                    return false;
            }
        }
    },
    PAY("已支付",1){
        @Override
        public Boolean canChange(OrderStatus orderStatus) {
            //因为退款接口一般都会有延迟,所以会先转化为“退款中”状态
            switch (orderStatus){
                case REFUNDING:
                    return true;
                default:
                    return false;
            }
        }
    },
    REFUNDING("退款中",2){
        @Override
        public Boolean canChange(OrderStatus orderStatus) {
            switch (orderStatus){
                case REFUNDED:
                case FAIL_REFUNDED:
                    return true;
                default:
                    return false;
            }
        }
    },
    REFUNDED("退款成功",3),
    FAIL_REFUNDED("退款失败",4),
    ;

    private final String name;
    private final int status;

    private OrderStatus(String name,int status){
        this.name = name;
        this.status = status;
    }

    //自定义转换方法
    public Boolean canChange(OrderStatus orderStatus){
        return false;
    }
}

调用方法:

public class EnumTest {

    public static void main(String[] args) {
        Boolean aBoolean = OrderStatus.NO_PAY.canChange(OrderStatus.PAY);
        String statusStr = aBoolean?"可以":"不可以";
        System.out.println("是否可以完成状态转换:"+ statusStr);

        Boolean flag = OrderStatus.REFUNDED.canChange(OrderStatus.FAIL_REFUNDED);
        String flagStr = flag?"可以":"不可以";
        System.out.println("是否可以完成状态转换:"+ flagStr);
    }
}

返回结果:

语法糖甜不甜?巧用枚举实现“状态”转换限制

这样我们就用枚举类实现了订单状态转换的限制。此例子只是为状态转换提供一种思路,具体的流程还需要根据自己系统中的业务来具体处理。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwgwxw.html