class 应作为职责清晰的协作单元,而非语法糖;需单一职责、明确边界、私有状态、公共接口、依赖注入、组合优于继承,并配合 typescript 和 eslint 提升可维护性。

用 class 语法写业务代码,核心不是“能不能用”,而是“怎么组织才不变成一坨难以调试、不敢动的巨石”。关键在于把 class 当作**职责清晰的协作单元**,而不是单纯替代 function 的语法糖。
只封装有明确边界和单一职责的逻辑
一个 class 应该代表一个可独立理解、测试和复用的概念,比如 UserProfileEditor、OrderValidator、ApiRetryClient。避免出现 UtilsClass 或 BusinessLogicManager 这类名字——它往往意味着职责已经模糊。
- 把数据获取、校验、状态更新、UI 渲染等不同层面的逻辑拆到不同 class 中
- 一个 class 内的方法尽量只操作自己的实例属性,少依赖外部 mutable 状态
- 如果某个方法需要大量参数或频繁修改入参,说明它可能属于另一个 class,或者该被拆成更小的行为
用私有字段 + 明确的公共接口控制访问
ES2022 起支持真正的私有字段(#field),这是维护性的分水岭。它强制你思考:哪些是别人该用的?哪些只是我内部实现的细节?
- 所有状态字段优先声明为私有:
#user = null;、#isSubmitting = false; - 只暴露必要的方法作为 public 接口,例如
submit()、reset(),而不是把validateForm()、sendRequest()全部公开 - 避免在 constructor 里做重操作(如发起请求、监听全局事件),改用显式初始化方法(如
init()),方便单元测试和按需启动
组合优于继承,用依赖注入解耦协作关系
业务代码里极少需要继承来复用行为。更多时候,是让一个 class “用”另一个 class 的能力。比如订单提交流程,不继承 ApiService,而是接收它作为构造参数:
class OrderSubmitter {
constructor(apiClient, notifier, logger) {
this.#api = apiClient;
this.#notifier = notifier;
this.#logger = logger;
}
}
- 依赖通过构造函数传入,便于替换 mock 实例做测试
- 每个依赖只承担一件事(
notifier只负责通知,不处理 API 错误) - 避免在 class 内部 new 其他业务 class,那会隐藏依赖、增加耦合
配合现代工具链,让 class 更健壮
class 本身不解决可维护性,但搭配 TypeScript 和 ESLint 就能发挥威力:
- TypeScript 的类型标注能立刻暴露字段误用、方法调用错参数等问题,尤其对私有字段+getter/setter 组合特别有效
- 开启
no-unused-vars和no-unused-private-class-members,自动清理死代码 - 用 JSDoc 注释关键方法的用途、参数含义和返回值,VS Code 能直接提示,比翻源码快得多
不复杂但容易忽略:class 是组织手段,不是银弹。真正提升可维护性的,是你每次新增方法前多问一句——它属于这里吗?它的输入输出是否干净?下次别人读这段代码,能不能三秒内看懂它在干什么、怎么被用、怎么被测。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











