很多人第一次接触 Clean Architecture 时,会产生一个非常典型的误解:
Use Case 必须只有一个方法。
尤其在 Android + Kotlin 的语境下,这种印象会被进一步强化:
调用时:
看起来既优雅又"标准"。久而久之,很多人就默认了:
但实际上,这只是 Android 社区逐渐形成的一种工程风格,并不是 Clean Architecture 的硬性规定。
真正的核心,从来不是"几个方法"
Clean Architecture 真正关心的是:
- 业务规则是否独立
- 依赖方向是否清晰
- 模块边界是否稳定
- 复杂度是否可控
而不是 Use Case 到底有几个方法。
所以,正确的理解应该是:
而不是:
登录、提交订单、刷新首页 Feed、发送消息……这些本质上都是系统行为。Use Case 的职责,是表达这些行为背后的业务边界。
为什么"单 invoke"会流行起来?
虽然不是官方规定,但它确实有明显的工程优势。
1. 强制职责单一,防止类膨胀
当你约定"一个 Use Case 只做一件事",类就很难无限膨胀。否则很容易出现这种情况:
class UserUseCase {
fun login()
fun logout()
fun refreshToken()
fun getProfile()
fun updateProfile()
fun deleteAccount()
// ...越来越多
}
最后 Use Case 退化成第二个 Repository,变成业务垃圾桶。
2. 更符合 Kotlin 的函数式风格
// operator invoke 写法
loginUseCase(username, password)
// 对比传统写法
loginUseCase.execute(username, password)
前者读起来更像"触发了一个业务动作",这也是 Kotlin operator invoke 在这里非常流行的原因。
3. 更容易组合业务流程
当 Use Case 足够纯粹时,组合它们会非常直观:
代码读起来就像在看一张业务流程图,这也是现代 Android 架构里非常常见的设计思路。
但多个方法并不是错误
很多人后来会走向另一个极端:Use Case 必须一个类一个方法。其实这同样容易变成形式主义。
来看这个例子:
这并没有任何问题。因为这三个操作属于同一个 Session 概念,共享同一批依赖,业务语义高度相关,聚合在一起反而更合理。
如果强行拆开,你可能会得到:
项目稍微大一点,就会出现几百个 Use Case 文件,维护体验未必更好。
Android 真正需要警惕的,不是"几个方法"
真正的问题是:把 Use Case 写成 Repository 的透传层。
很多人会直接把这种写法定义成反模式,但其实逻辑简单本身并不是问题。
真正的问题是:整个项目是否已经开始机械分层。
如果工程里 200 个 Use Case 全是 repo.xxx() 的透传,那说明 Use Case 已经失去了业务边界意义,只是在为了架构而架构。
小逻辑不等于没价值
这一点很重要,举个例子:
逻辑不复杂,但它依然有价值。它表达的是**"是否登录"**这个业务语义,而不是"用户数据结构"。它把业务语义、UI 关注点和数据模型隔离开了——这本身就已经是一种业务边界抽象。
真正有价值的 Use Case 是什么样的?
成熟的 Use Case,通常会承担这些职责:业务规则、数据编排、多数据源协调、缓存控制、权限判断、状态流转。
这里有业务规则、有流程控制、有数据编排,ViewModel 不需要知道任何实现细节。这才是 Use Case 开始真正体现价值的地方。
最后
很多 Android 开发者学习 Clean Architecture 时,容易把架构思想学成类模板规范,于是开始执着于:
- Use Case 必须一个方法
- Repository 必须有接口
- 必须三层、必须 DTO、必须 Mapper……
但 Clean Architecture 真正想解决的,一直都是:复杂度失控、依赖混乱、业务耦合、测试困难。
而不是仅仅"类到底长什么样"。
总结
Use Case 不是一种固定的类结构,而是一种业务边界的表达方式。
一个方法可以,多个方法也可以。
invoke可以,execute也可以。在简单场景下,甚至不用 Use Case 也完全没问题 (但是商业级项目很少有简单场景)。真正重要的,而是:你的架构有没有真正帮助你控制复杂度。