如何在Kotlin中简化复杂的分类判断逻辑?
优化后的简洁实现方案
方案1:直接内联定义规则列表
省去冗余的单独函数,直接把所有分类规则集中定义在列表中,代码更紧凑直观:
class Abc { private val categoryRules by lazy { listOf( Item("Low") { itemOne, itemTwo -> itemOne < 90 && itemTwo < 60 }, Item("Normal") { itemOne, itemTwo -> itemOne in 90..119 && itemTwo in 60..80 }, Item("Elevated") { itemOne, itemTwo -> itemOne in 120..129 && itemTwo < 80 }, Item("High") { itemOne, itemTwo -> itemOne in 130..139 || itemTwo in 80..89 }, Item("Very high") { itemOne, itemTwo -> itemOne in 140..179 || itemTwo in 90..119 }, Item("Extremely High") { itemOne, itemTwo -> itemOne >= 180 || itemTwo >= 120 } ) } fun getItem(itemOne: Int, itemTwo: Int): Item { return categoryRules.firstOrNull { it.condition(itemOne, itemTwo) } ?: Item("Default") { _, _ -> false } } } data class Item( val itemName: String, val condition: (Int, Int) -> Boolean, )
方案2:用数据类封装阈值规则(更利于测试)
把每个分类的阈值逻辑抽成结构化的数据类,规则更清晰,单独测试和修改都更方便:
// 封装分类阈值规则,明确每个维度的限制条件 data class CategoryThreshold( val name: String, val itemOneRange: ClosedRange<Int>? = null, val itemOneLowerThan: Int? = null, val itemOneGreaterOrEqual: Int? = null, val itemTwoRange: ClosedRange<Int>? = null, val itemTwoLowerThan: Int? = null, val itemTwoGreaterOrEqual: Int? = null, val logic: Logic = Logic.AND // 多条件的逻辑关系:AND/OR ) enum class Logic { AND, OR } class Abc { private val categoryThresholds by lazy { listOf( CategoryThreshold( name = "Low", itemOneLowerThan = 90, itemTwoLowerThan = 60 ), CategoryThreshold( name = "Normal", itemOneRange = 90..119, itemTwoRange = 60..80 ), CategoryThreshold( name = "Elevated", itemOneRange = 120..129, itemTwoLowerThan = 80 ), CategoryThreshold( name = "High", itemOneRange = 130..139, itemTwoRange = 80..89, logic = Logic.OR ), CategoryThreshold( name = "Very high", itemOneRange = 140..179, itemTwoRange = 90..119, logic = Logic.OR ), CategoryThreshold( name = "Extremely High", itemOneGreaterOrEqual = 180, itemTwoGreaterOrEqual = 120, logic = Logic.OR ) ) } fun getItem(itemOne: Int, itemTwo: Int): Item { val matchedThreshold = categoryThresholds.firstOrNull { threshold -> val itemOneMatch = when { threshold.itemOneRange != null -> itemOne in threshold.itemOneRange threshold.itemOneLowerThan != null -> itemOne < threshold.itemOneLowerThan threshold.itemOneGreaterOrEqual != null -> itemOne >= threshold.itemOneGreaterOrEqual else -> true // 无限制则默认匹配 } val itemTwoMatch = when { threshold.itemTwoRange != null -> itemTwo in threshold.itemTwoRange threshold.itemTwoLowerThan != null -> itemTwo < threshold.itemTwoLowerThan threshold.itemTwoGreaterOrEqual != null -> itemTwo >= threshold.itemTwoGreaterOrEqual else -> true } when (threshold.logic) { Logic.AND -> itemOneMatch && itemTwoMatch Logic.OR -> itemOneMatch || itemTwoMatch } } return matchedThreshold?.let { Item(it.name) { _, _ -> true } } ?: Item("Default") { _, _ -> false } } } data class Item( val itemName: String, val condition: (Int, Int) -> Boolean, )
优化说明
- 减少冗余:方案1省去了6个重复的
getXxxItem函数,代码结构更紧凑。 - 简化查找逻辑:用Kotlin标准库的
firstOrNull替代手动循环,代码更简洁可靠。 - 提升可测试性:方案2把阈值规则结构化,测试时可以单独验证每个阈值的正确性,修改规则也无需改动lambda逻辑。
- IntRange覆盖性:你所有的条件都可以用
IntRange配合简单比较运算符实现,完全覆盖原有逻辑,比如itemOne < 90等价于itemOne in Int.MIN_VALUE..89,直接用<更直观。
内容的提问来源于stack exchange,提问作者Compose Learner
相关产品推荐
相关产品推荐

