You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin如何实现支持多分类归属、同值单例的角色枚举结构

最优实现方案

核心逻辑是将角色实体与角色分类解耦:所有角色作为唯一枚举实例全局统一定义,分类作为角色的标签属性存在,预构建分类到角色的索引满足查询需求,从根源上避免同角色多实例的问题,同时支持后续灵活扩展分类。

完整实现代码

// 角色分类定义,后续新增分类直接在此追加枚举值即可,无需重构核心逻辑
enum class RoleCategory {
    CATEGORY_A,
    CATEGORY_B
}

// 全局唯一角色枚举,所有角色在此统一定义,保证单实例
enum class UserRole(
    val roleName: String,
    val categories: Set<RoleCategory>,
    // 不同分类的差异化参数可通过可选字段定义,也可拆分为独立映射表避免主构造参数膨胀
    private val categoryBSecondParam: String? = null
) {
    ROLE_A(
        roleName = "A",
        categories = setOf(RoleCategory.CATEGORY_A, RoleCategory.CATEGORY_B),
        categoryBSecondParam = "A"
    ),
    ROLE_B(
        roleName = "B",
        categories = setOf(RoleCategory.CATEGORY_A)
    ),
    ROLE_C(
        roleName = "C",
        categories = setOf(RoleCategory.CATEGORY_A)
    ),
    ROLE_D(
        roleName = "D",
        categories = setOf(RoleCategory.CATEGORY_A)
    ),
    ROLE_E(
        roleName = "E",
        categories = setOf(RoleCategory.CATEGORY_B),
        categoryBSecondParam = "E"
    ),
    ROLE_F(
        roleName = "F",
        categories = setOf(RoleCategory.CATEGORY_B),
        categoryBSecondParam = "F"
    );

    /**
     * 获取B类角色专属参数,非B类角色调用会抛异常
     */
    fun getBClassSecondParam(): String {
        check(RoleCategory.CATEGORY_B in categories) { "当前角色不属于B类,无该参数" }
        return categoryBSecondParam!!
    }

    companion object {
        // 按角色名查询实例
        fun fromRoleName(roleName: String): UserRole? =
            values().singleOrNull { it.roleName == roleName }

        // 预构建分类索引,查询分类下角色时间复杂度O(1)
        private val categoryIndex: Map<RoleCategory, List<UserRole>> =
            values().flatMap { role ->
                role.categories.map { it to role }
            }.groupBy({ it.first }, { it.second })

        // 查询指定分类下的全部角色
        fun listByCategory(category: RoleCategory): List<UserRole> =
            categoryIndex[category] ?: emptyList()
    }
}

扩展类型安全校验(可选)

如果需要在编译期限制方法只能接收指定分类的角色,可以用value class做轻量包装,避免传错角色类型:

@JvmInline
value class ARole(val inner: UserRole) {
    init {
        require(RoleCategory.CATEGORY_A in inner.categories) { "传入角色不属于A类" }
    }
}

@JvmInline
value class BRole(val inner: UserRole) {
    val secondParam: String get() = inner.getBClassSecondParam()
    init {
        require(RoleCategory.CATEGORY_B in inner.categories) { "传入角色不属于B类" }
    }
}

业务方法需要A类角色时直接定义参数为ARole类型即可,从UserRole转换时会自动做合法性校验。

方案特性

  • 所有角色全局唯一实例,不存在同角色重复定义、对象不一致的问题
  • 天然支持一个角色归属多个分类,只需要在角色的categories集合中追加对应分类值即可
  • 分类扩展成本极低,新增分类不需要修改原有角色、分类查询的核心逻辑
  • 分类查询性能高,预构建的索引避免每次全量遍历角色
  • 兼容不同分类的差异化参数需求,参数校验逻辑可统一收敛

内容的提问来源于stack exchange,提问作者Guy Schwartzberg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 09:42:26