1 分钟 学会酷炫技能,关于枚举类型,你绝对没用过如此酷炫的使用方式!

2,729 阅读5分钟

大家好,我是五阳,最近在偷学兄弟团队的代码,收获较多,现在我给大家做一个期末汇报。

枚举类型适用于有限且固定值的场景,比如状态、返回值类型等类型字段,可以将所有情况枚举出来。最近我发现了一些新颖的使用方式,并想分享给大家。

为了增加系统的灵活性,有时候我们不会在代码中写死一些限制条件,比如每天的购买数量限制。这时候我们可以从动态字典服务中获取这些值。

举个例子,下面的工具方法可以调用公司内部的工具类来获取动态配置的值。

public static int getMaxBuyCountDaily() {
   return DynamicKeyUtil.getInt("max_buy_count_daily", 10);
}

一般情况下,都是这么写,我本来也坚信这是理所当然的。然而,令我意外的是,直到最近一天,当我偷偷地学习了其他团队的代码后,我发现了一种全新的写作方式,一种神奇的方式!这让我对枚举类型有了全新的认识。

public enum CommonDynamicKeyEnum {
   MAX_BUY_COUNT_DAILY("max_buy_count_daily", 10),
   DEGRADE_CHECK_BUY_COUNT_DAILY("degrade_check_buy_count_daily", false);
   
   private String name;
   private Object value;
   
   CommonDynamicKeyEnum(String name, Object value) {
      this.value = value;
      this.name = name;
   }
   public Boolean getBoolean() {
      return DynamicKeyUtil.getBoolean(name, (Boolean) value);
   }
   public int getInt() {
      return DynamicKeyUtil.getInt(name, (int) value);
   }
}

在上面的代码中,CommonDynamicKeyEnum 是一个枚举类型,其中包含两个字段,动态Key和默认值。当业务代码需要获取动态值时,可以通过 CommonDynamicKeyEnum.MAX_BUY_COUNT_DAILY.getInt() 来获取。

起初我看到这段代码时,对于枚举类型的使用感到有些滥用。因为在我之前的认知中,枚举类型通常是这样使用的。

public enum OrderStatusEnum {
   INIT(1, "初始化"),
   SUCCESS(2, "成功"),
   FAIL(3, "失败");

   private int value;
   private String name;

   OrderStatusEnum(int value, String name) {
      this.value = value;
      this.name = name;
   }   
}

但是我尝试使用枚举类型改进我们的代码后,发现动态Key 场景使用枚举类型是非常好的实践。这样可以将相关的动态配置封装在一个枚举类中,并避免代码的重复。因为如果使用 DynamicKeyUtil.getInt 来调用和封装静态方法,至少需要三行代码来新增一个动态KEY。

然而使用枚举类型,只需要一行代码即可实现。例如 MAX_BUY_COUNT_DAILY("max_buy_count_daily", 10)

第二种枚举使用方式

如果我问你:如何管理接口的返回值,你认为应该如何处理呢?一般情况下,我都是使用 static int 方式管理。

例如这种方式 public static final int SUCCESS_CODE = 0;

现在我推荐使用枚举的方式管理返回值!

public enum CommmonCode {
   SUCCESS(0, "成功"),
   FAIL(1, "失败");

   private String name;
   private int value;

   CommmonCode(int value, String name) {
      this.value = value;
      this.name = name;
   }

   public BizException toBizException() {
      return new BizException(value, name);
   }
   
    public BizException throwBizException() {
      throw new BizException(value, name);
   }
}

此时 你可以使用 CommonCode.FAIL.toBizException() 就可以直接构造异常,也可以使用 CommonCode.FAIL.throwBizException() 抛出异常。

这样我们只需要记住返回值的枚举类是哪一个,然后通过 IDE 选择合适的返回值,直接调用相关的工具方法,构建异常 或者抛出异常。这样总比 苦哈哈的 使用 new BizException(code, "message");的方式强多了。

以上两种使用方式虽然只节省了一点点时间,但是这种使用方式确实比之前我常用的方式 要更加优雅和简洁,希望对你有帮助。

我的开源项目

最后夹带一点私货,五阳最近花了3个月的时间完成一个开源项目。

开源3周以来,已有近 230 多个关注和Fork

Gitee:gitee.com/juejinwuyan…

GitHub github.com/juejin-wuya…

开源平台上有很多在线商城系统,功能很全,很完善,关注者众多,然而实际业务场景非常复杂和多样化,开源的在线商城系统很难完全匹配实际业务,广泛的痛点是

  • 功能堆砌,大部分功能用不上,需要大量裁剪;
  • 逻辑差异点较多,需要大量修改;
  • 功能之间耦合,难以独立替换某个功能。

由于技术中间件功能诉求较为一致,使用者无需过多定制化,技术中间件开源项目以上的痛点不明显,然而电商交易等业务系统虽然通用性较多,但各行业各产品的业务差异化极大,所以导致以上痛点比较明显

所以我在思考,有没有一个开源系统,能提供电商交易的基础能力,能让开发者搭积木的方式,快速搭建一个完全契合自己业务的新系统呢?

  • 他们可以通过编排和配置选择自己需要的功能,而无需在一个现成的开源系统上进行裁剪
  • 他们可以轻松的新增扩展业务的差异化逻辑,不需要阅读然后修改原有的系统代码!
  • 他们可以轻松的替换掉他们认为垃圾的、多余的系统组件,而不需要考虑其他功能是否会收到影响

开发者们,可以择需选择需要的能力组件,组件中差异化的部分有插件扩展点能轻松扩展。或者能支持开发者快速的重新写一个完全适合自己的新组件然后编排注册到系统中?

memberclub 就是基于这样的想法而设计的。 它的定位是电商类交易系统工具箱, 以SDK方式对外提供通用的交易能力,能让开发者像搭积木方式,从0到1,快速构建一个新的电商交易系统!

image.png

具体介绍可参见

Gitee开源地址gitee.com/juejinwuyan…

GitHub开源地址 : github.com/juejin-wuya…

在这个项目中你可以学习到 SpringBoot 集成 以下框架或组件。

  1. Mybatis、Mybatis-plus 集成多数据源
  2. Sharding-jdbc 多数据源分库分表
  3. redis/redisson 缓存
  4. Apollo 分布式配置中心
  5. Spring Cloud 微服务全家桶
  6. RabbitMq 消息队列
  7. H2 内存数据库
  8. Swagger + Lombok + MapStruct

同时你也可以学习到以下组件的实现原理

  1. 流程引擎的实现原理
  2. 扩展点引擎实现原理
  3. 分布式重试组件实现原理
  4. 通用日志组件实现原理 参考:juejin.cn/post/740727…
  5. 商品库存实现原理: 参考:juejin.cn/post/731377…
  6. 分布式锁组件: 参考:
  7. Redis Lua的使用
  8. Spring 上下文工具类 参考: juejin.cn/post/746927…