最新消息:从今天开始,做一个有好习惯的人。

如何利用枚举策略降低系统的复杂性

解决方案 迷路的老鼠 3887浏览 2评论

枚举我们应用的场景很多,也有一部分的高阶用户可以降低系统的复杂度,实现系统的解耦和封装,本文将从某一个场景举例说明。

场景:现有一接口,调用方传入一个枚举值比如1/2/3/4等,需要返回一个对象,该对象的内容根据枚举值一一对应,对象属性值没有重复性。

场景经过简化,实际需求比这个复杂很多,我们这里只是说一下新的思路。

如果按照以往的写法,我们肯定是if esle或者switch来处理,结构看着也挺清晰,但是封装性不好,代码耦合性可能会比较高,也不美观。

如果使用枚举策略来写呢?我们知道枚举是可以实现接口的,所以我们先定义一组枚举,枚举值分别是1/2/3/4,如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
@Getter
    enum CalOrderParamEnum{
        /**
         * 取消
         */
        ORDER_CANCEL(1) ,
        /**
         * 接单
         */
        ORDER_ACCEPT(2),
        /**
         * 服务中
         */
        ORDER_SERVICING(3),
        /**
         * 已完成
         */
        ORDER_COMPLETE(4),
        /**
         * 旁听的已完成
         */
        CASE_ORDER_COMPLETE(5);

        /**
         * 对应状态
         */
        private int status;

        CalOrderParamEnum(int status) {
            this.status = status;
        }

        /**
         * 根据状态码获取策略枚举
         *
         * @param code
         * @return
         */
        public static CalOrderParamEnum getByCode(int code) {
            for (CalOrderParamEnum calOrderParamEnum : CalOrderParamEnum.values()) {
                if (calOrderParamEnum.getStatus() == code) {
                    return calOrderParamEnum;
                }
            }
            return null;
        }

定义完枚举之后,需要让每个枚举做自己的事情,怎么处理呢?

我们知道枚举是可以实现接口的,所以定义一个接口类


1
2
3
4
5
6
7
8
9
/**
     * 计算接口
     *
     * @param oldStatus
     * @param orderNo
     * @param sku
     * @return
     */
    QuestionOrderCallBackOut cal(Integer oldStatus, String orderNo, String sku);

让枚举实现接口类,枚举就会变成这样


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
@Getter
    enum CalOrderParamEnum implements CalOrderParam {
        /**
         * 取消
         */
        ORDER_CANCEL(QuestionStatusEnum.ORDER_CANCEL.getCode()) {
            @Override
            public QuestionOrderCallBackOut cal(Integer oldStatus, String orderNo, String sku) {
                return null;
            }
        },
        /**
         * 接单
         */
        ORDER_ACCEPT(QuestionStatusEnum.ORDER_ACCEPT.getCode()) {
            @Override
            public QuestionOrderCallBackOut cal(Integer oldStatus, String orderNo, String sku) {
                return null;
            }
        },
        /**
         * 服务中
         */
        ORDER_SERVICING(QuestionStatusEnum.ORDER_SERVICING.getCode()) {
            @Override
            public QuestionOrderCallBackOut cal(Integer oldStatus, String orderNo, String sku) {
                return null;
            }
        },
        /**
         * 已完成
         */
        ORDER_COMPLETE(QuestionStatusEnum.ORDER_COMPLETE.getCode()) {
            @Override
            public QuestionOrderCallBackOut cal(Integer oldStatus, String orderNo, String sku) {
                return null;
            }
        },
        /**
         * 旁听的已完成
         */
        CASE_ORDER_COMPLETE(QuestionStatusEnum.CASE_ORDER_COMPLETE.getCode()) {
            @Override
            public QuestionOrderCallBackOut cal(Integer oldStatus, String orderNo, String sku) {
                return null;
            }
        };

        /**
         * 对应状态
         */
        private int status;

        CalOrderParamEnum(int status) {
            this.status = status;
        }

        /**
         * 根据状态码获取策略枚举
         *
         * @param code
         * @return
         */
        public static CalOrderParamEnum getByCode(int code) {
            for (CalOrderParamEnum calOrderParamEnum : CalOrderParamEnum.values()) {
                if (calOrderParamEnum.getStatus() == code) {
                    return calOrderParamEnum;
                }
            }
            return null;
        }

    }

我们只需要在实现的这个方法里面加上各自的参数封装就行了,每块的业务逻辑独立起来,调用的时候就很简单了


1
2
3
4
5
6
7
8
// 根据新状态获取枚举策略
CalOrderParam.CalOrderParamEnum calOrderParamEnum = CalOrderParam.CalOrderParamEnum.getByCode(newStatus);
if (calOrderParamEnum == null) {
    return true;
}

// 根据枚举策略计算响应的参数
QuestionOrderCallBackOut questionOrderCallBackOut = calOrderParamEnum.cal(oldStatus, orderNo, sku);

这个结构是不是看起来显得很舒服?下面把完整的枚举策略类贴出来吧,仅供参考


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/**
 * 组装返回参数枚举
 *
 * @author weitao
 * @date 2019/4/19
 */
public interface CalOrderParam {

    /**
     * 计算接口
     *
     * @param oldStatus
     * @param orderNo
     * @param sku
     * @return
     */
    QuestionOrderCallBackOut cal(Integer oldStatus, String orderNo, String sku);

    @Getter
    enum CalOrderParamEnum implements CalOrderParam {
        /**
         * 取消
         */
        ORDER_CANCEL(QuestionStatusEnum.ORDER_CANCEL.getCode()) {
            @Override
            public QuestionOrderCallBackOut cal(Integer oldStatus, String orderNo, String sku) {
                QuestionOrderCallBackOut questionOrderCallBackOut = QuestionOrderCallBackOut.builder().orderCode(orderNo).eventName(MTOrderStausEnum.OrderReturnInfo.UNPAY_CANCEL.getEventType())  .resultType(MTOrderStausEnum.OrderReturnInfo.UNPAY_CANCEL.getResultType()).build();
                return questionOrderCallBackOut;
            }
        },
        /**
         * 接单
         */
        ORDER_ACCEPT(QuestionStatusEnum.ORDER_ACCEPT.getCode()) {
            @Override
            public QuestionOrderCallBackOut cal(Integer oldStatus, String orderNo, String sku) {
                Map<String, Object> extData = new HashMap<>(10);
                extData.put("bakVarchar1", sku == null ? StringUtils.EMPTY : sku);
                return QuestionOrderCallBackOut.builder().orderCode(orderNo).eventName(MTOrderStausEnum.OrderReturnInfo.PAIED_DOCTOR_CONFIRM.getEventType())
                        .resultType(MTOrderStausEnum.OrderReturnInfo.PAIED_DOCTOR_CONFIRM.getResultType()).extData(extData).build();
            }
        },
        /**
         * 服务中
         */
        ORDER_SERVICING(QuestionStatusEnum.ORDER_SERVICING.getCode()) {
            @Override
            public QuestionOrderCallBackOut cal(Integer oldStatus, String orderNo, String sku) {
                Map<String, Object> extData = new HashMap<>(10);
                extData.put("deliveredTime", STDateUtils.format(new Date(), STDateUtils.NORM_DATETIME_PATTERN));
                return QuestionOrderCallBackOut.builder().orderCode(orderNo).eventName(MTOrderStausEnum.OrderReturnInfo.PAIED_DOCTOR_ACCPET.getEventType())
                        .resultType(MTOrderStausEnum.OrderReturnInfo.PAIED_DOCTOR_ACCPET.getResultType()).extData(extData).build();
            }
        },
        /**
         * 已完成
         */
        ORDER_COMPLETE(QuestionStatusEnum.ORDER_COMPLETE.getCode()) {
            @Override
            public QuestionOrderCallBackOut cal(Integer oldStatus, String orderNo, String sku) {
                Map<String, Object> extData = new HashMap<>(10);
                extData.put("doneTime", STDateUtils.format(new Date(), STDateUtils.NORM_DATETIME_PATTERN));
                return QuestionOrderCallBackOut.builder().orderCode(orderNo).eventName(MTOrderStausEnum.OrderReturnInfo.PAIED_DOCTOR_COMPLATE.getEventType())
                        .resultType(MTOrderStausEnum.OrderReturnInfo.PAIED_DOCTOR_COMPLATE.getResultType()).extData(extData).build();
            }
        },
        /**
         * 旁听的已完成
         */
        CASE_ORDER_COMPLETE(QuestionStatusEnum.CASE_ORDER_COMPLETE.getCode()) {
            @Override
            public QuestionOrderCallBackOut cal(Integer oldStatus, String orderNo, String sku) {
                Map<String, Object> extData = new HashMap<>(10);
                extData.put("deliveredTime", STDateUtils.format(new Date(), STDateUtils.NORM_DATETIME_PATTERN));
                extData.put("doneTime", STDateUtils.format(new Date(), STDateUtils.NORM_DATETIME_PATTERN));
                return QuestionOrderCallBackOut.builder().orderCode(orderNo).eventName(MTOrderStausEnum.OrderReturnInfo.CASE_PAIED_DOCTOR_COMPLATE.getEventType())
                        .resultType(MTOrderStausEnum.OrderReturnInfo.CASE_PAIED_DOCTOR_COMPLATE.getResultType()).extData(extData).build();
            }
        };

        /**
         * 对应状态
         */
        private int status;

        CalOrderParamEnum(int status) {
            this.status = status;
        }

        /**
         * 根据状态码获取策略枚举
         *
         * @param code
         * @return
         */
        public static CalOrderParamEnum getByCode(int code) {
            for (CalOrderParamEnum calOrderParamEnum : CalOrderParamEnum.values()) {
                if (calOrderParamEnum.getStatus() == code) {
                    return calOrderParamEnum;
                }
            }
            return null;
        }

    }
}

转载请注明:迷路的老鼠 » 如何利用枚举策略降低系统的复杂性

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (2)

  1. 阅读瞎理解:杀鸡焉用牛刀
    wa5年前 (2019-09-30)回复
    • 嗯,可以这么理解,不过越复杂的逻辑使用这种方式越简单
      迷路的老鼠5年前 (2019-09-30)回复