首页/开发/代码质量与评审速查/手法:Extract Class(提炼类)
重构手法62 条

手法:Extract Class(提炼类)

一个类承担了两类职责时,把其中一类搬进新类:字段、方法、以及它们之间的依赖一起迁移;提炼后原类以组合引用新类,职责边界显式化。

提炼类是什么

当一个类承担了两类职责时,把其中一类搬进新类:字段、方法以及它们之间的依赖一起迁移,原类改以组合方式引用新类。提炼之后职责边界变得显式,两类变化各自只影响一个类,测试与复用也更容易。

基本信息

典型信号类中字段按用途可分为两簇,方法也按簇聚集
做法建新类、搬字段、搬方法、旧类保留组合引用
收益每个类只对一类变化负责
相关手法提取子类、以委托替代继承
配套检查搬完后原类是否仍然是一个完整概念

典型使用场景

  • 人员类里混着联系方式字段与地址字段
  • 订单类同时管金额计算与通知发送
  • 服务类既做参数校验又做外部接口调用
  • 报表类既取数又负责排版输出
  • 配置类里混着解析逻辑与默认值合并

结构变化

结构变化
// 之前:联系方式与人员信息挤在一个类里
class Person { name, officeAreaCode, officeNumber }

// 之后:联系方式独立成类,人员持有它
class Person { name, TelephoneNumber phone }
class TelephoneNumber { areaCode, number }
// 联系方式的变化不再影响人员类

几种拆法对比

拆法依据风险
提炼类字段与方法按职责分组拆得过细会增加跳转与协调成本
提取子类共享行为存在层次差异继承会固化关系,后续不易调整
提取独立模块整块功能可独立部署接口设计不当会变成远程调用开销
拆分的判断依据是变化原因,不是字段数量:问一句这两组字段会不会因为同一类需求一起改,答案是不会,才值得分开。
新类直接暴露全部字段等于没封装:原类的内部结构只是换了位置,调用方仍能绕开约束修改状态。
拆完检查命名:新类的名字应当是一个领域概念,例如联系方式、价格策略;如果只能起成工具类、管理器这类名字,多半说明还没找到真正的职责边界。

易错点

  • 按字段数量而不是职责划分:拆出的类依旧混杂,只是体积变小
  • 新类暴露全部字段:封装没有建立,约束可以从外部绕过
  • 拆完原类只剩转发方法:调用链变长,回头又想内联回来
  • 一次性大范围拆分类:影响面不可控,应围绕最痛的一处职责开始

数据来源与参考

  • 《重构》第 2 版 · 第 7 章(Extract Class)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌