为何谷歌推荐用类实现用例而非Kotlin顶层函数?
为什么谷歌推荐用「动词+UseCase」格式的类而非顶层函数?
从语义层面来说,类和接口一般充当名词,方法/函数则充当动词,这符合大多数人的自然命名习惯——比如我们会认为Car类拥有getBrand()方法,而非定义一个带invoke()方法的GetBrand类。
但谷歌在《应用架构指南》中给出的用例命名规范,却建议采用「现在时动词+可选名词/对象+UseCase」的格式,还给出了这样的Kotlin实现示例:
class FormatDateUseCase(userRepository: UserRepository) { private val formatter = SimpleDateFormat( userRepository.getPreferredDateFormat(), userRepository.getPreferredLocale() ) operator fun invoke(date: Date): String { return formatter.format(date) } }
这类实现本质是充当函数的类,谷歌推荐它而非直接使用顶层函数,核心是因为它解决了顶层函数的诸多局限性,背后有这些设计考量:
- 状态与依赖的合理持有:UseCase类可以在内部缓存依赖实例(比如示例中的
SimpleDateFormat),避免每次调用都重复初始化资源。如果用顶层函数,要么每次调用都创建新实例造成浪费,要么依赖全局变量引发状态污染。 - 适配依赖注入框架:在Hilt、Dagger这类依赖注入框架中,类可以通过构造函数接收依赖,还能被框架统一管理生命周期、实现注入。顶层函数很难做到这一点,要么手动传递所有依赖,要么依赖全局单例,灵活性和可维护性都差很多。
- 测试成本更低:测试时可以轻松替换构造函数中的依赖(比如传入Mock的
UserRepository),快速隔离测试场景。顶层函数如果依赖外部资源,测试时需要额外的Mock手段,复杂度更高。 - 明确架构边界:在分层架构中,UseCase作为数据层和UI层的中间层,用类的形式能清晰划分业务逻辑的边界,让所有核心业务逻辑都被统一封装和管理。零散的顶层函数容易让代码结构混乱,不利于长期维护。
- 兼顾简洁性与类的优势:借助Kotlin的
operator fun invoke()特性,这类类可以像普通函数一样被调用(比如FormatDateUseCase(repo)(Date())),既保留了类的所有优势,又拥有函数调用的简洁性,平衡了语义规范和实用性。
内容的提问来源于stack exchange,提问作者xogon
相关产品推荐
相关产品推荐

