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

如何为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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 19:52:39