如何为SmartHome类多方法添加无样板代码的状态验证检查?
SmartHome类状态校验的无重复实现方案
需求说明
turnOnTv()和turnOnLight()仅在deviceStatus == "off"时可执行- 其余所有方法仅在
deviceStatus == "on"时可执行 - 要求不在每个方法内重复编写条件判断
实现思路1:状态委托类(纯Kotlin无依赖)
通过拆分不同状态下的行为,用两个委托类分别处理"off"和"on"状态的操作,让SmartHome类根据当前状态动态切换委托对象,把校验逻辑集中管理,避免重复代码。
步骤1:定义操作接口
先把所有设备操作抽象成统一接口:
interface SmartHomeOperations { fun turnOnTv() fun turnOnLight() fun turnOffTv() fun turnOffLight() fun adjustTvVolume(level: Int) fun dimLight(brightness: Int) }
步骤2:实现不同状态的委托类
分别编写对应状态的操作实现,不符合状态的方法直接抛出异常或做提示:
// 设备关闭状态的操作实现 class OffStateOperations(private val parent: SmartHome) : SmartHomeOperations { override fun turnOnTv() { parent.deviceStatus = "on" println("TV turned on") // 这里写实际开电视的业务逻辑 } override fun turnOnLight() { parent.deviceStatus = "on" println("Light turned on") // 这里写实际开灯光的业务逻辑 } // 以下方法在off状态下不可执行 override fun turnOffTv() = throw IllegalStateException("设备未开启,无法关闭电视") override fun turnOffLight() = throw IllegalStateException("设备未开启,无法关闭灯光") override fun adjustTvVolume(level: Int) = throw IllegalStateException("设备未开启,无法调节电视音量") override fun dimLight(brightness: Int) = throw IllegalStateException("设备未开启,无法调节灯光亮度") } // 设备开启状态的操作实现 class OnStateOperations(private val parent: SmartHome) : SmartHomeOperations { // 以下方法在on状态下不可执行 override fun turnOnTv() = throw IllegalStateException("电视已经处于开启状态") override fun turnOnLight() = throw IllegalStateException("灯光已经处于开启状态") override fun turnOffTv() { println("TV turned off") // 这里写实际关电视的业务逻辑 } override fun turnOffLight() { println("Light turned off") // 这里写实际关灯光的业务逻辑 } override fun adjustTvVolume(level: Int) { println("TV volume adjusted to $level") // 这里写实际调音量的业务逻辑 } override fun dimLight(brightness: Int) { println("Light dimmed to $brightness%") // 这里写实际调亮度的业务逻辑 } }
步骤3:改造SmartHome类
让SmartHome持有当前状态的委托对象,所有操作直接委托给对应状态类,状态变化时自动切换委托:
class SmartHome { var deviceStatus: String = "off" private set(newStatus) { field = newStatus // 状态变更时切换委托实例 currentOperations = if (newStatus == "on") OnStateOperations(this) else OffStateOperations(this) } private var currentOperations: SmartHomeOperations = OffStateOperations(this) // 所有方法直接转发给当前状态的实现类 fun turnOnTv() = currentOperations.turnOnTv() fun turnOnLight() = currentOperations.turnOnLight() fun turnOffTv() = currentOperations.turnOffTv() fun turnOffLight() = currentOperations.turnOffLight() fun adjustTvVolume(level: Int) = currentOperations.adjustTvVolume(level) fun dimLight(brightness: Int) = currentOperations.dimLight(brightness) }
实现思路2:注解+AOP(进阶方案)
如果项目允许引入AOP依赖(比如AspectJ),可以用注解标记方法的允许状态,通过切面统一做校验,代码侵入性更低:
步骤1:定义状态校验注解
@Target(AnnotationTarget.FUNCTION) annotation class AllowedStatus(val status: String)
步骤2:给SmartHome方法标记注解
class SmartHome { var deviceStatus: String = "off" @AllowedStatus("off") fun turnOnTv() { /* 开电视业务逻辑 */ } @AllowedStatus("off") fun turnOnLight() { /* 开灯光业务逻辑 */ } @AllowedStatus("on") fun turnOffTv() { /* 关电视业务逻辑 */ } @AllowedStatus("on") fun turnOffLight() { /* 关灯光业务逻辑 */ } @AllowedStatus("on") fun adjustTvVolume(level: Int) { /* 调音量业务逻辑 */ } @AllowedStatus("on") fun dimLight(brightness: Int) { /* 调亮度业务逻辑 */ } }
步骤3:编写切面统一校验
@Aspect class StatusCheckAspect { @Around("@annotation(AllowedStatus)") fun checkStatus(proceedingJoinPoint: ProceedingJoinPoint): Any? { val smartHome = proceedingJoinPoint.target as SmartHome val allowedStatus = proceedingJoinPoint.signature .getAnnotation(AllowedStatus::class.java) .status if (smartHome.deviceStatus != allowedStatus) { throw IllegalStateException("该方法仅在设备处于[$allowedStatus]状态时可执行") } return proceedingJoinPoint.proceed() } }
方案对比
- 状态委托类:纯Kotlin实现,无额外依赖,逻辑直观,适合小型或基础项目
- AOP注解方案:代码侵入性极低,校验逻辑完全集中,适合有大量状态校验需求的中大型项目
内容的提问来源于stack exchange,提问作者Pavel Lesyuk
相关产品推荐
相关产品推荐

