重新组织数据
Tip
引用和值的混淆经常会造成问题
自封装字段(Self Encapsulate Field)
title | content |
---|---|
场景 | 直接访问一个字段,但与字段之间的耦合关系逐渐变得笨拙 |
意义 | 控制作用域 |
定义 | 为这个字段建立取值/设值函数,并且只以这些函数来访问字段。 |
做法 | 你的类中存在一个public字段。将它声明为private,并提供相应的访问函数。 |
注意 |
拆分变量(Split Variable)
title | content |
---|---|
场景 | 同一个变量承担两件不同的事情,会令代码阅读者糊涂。 |
意义 | |
定义 | |
做法 | |
注意 |
拆分阶段(Split Phase)
Tip
如果在另一个代码库中使用了该变量,这就是一个”已发布变量”(published variable),此时不能进行这个重构。
title | content |
---|---|
场景 | 一段代码在同时处理两件不同的事(如一个大函数 或 一个遍历 返回两个变量) |
意义 | 到了需要修改的时候,我就可以单独处理每个主题,而不必同时在脑子里考虑两个不同的主题 |
定义 | 就是把一大段行为分成顺序执行的两个阶段,每个步骤负责的任务全然不同 |
做法 | |
注意 |
字段改名(Rename Field)
title | content |
---|---|
场景 | |
意义 | |
定义 | |
做法 | |
注意 |
以查询取代派生变量(Replace Derived Variable with Query)
title | content |
---|---|
场景 | 可变数据是软件中最大的错误源头之一。 对数据的修改常常导致代码的各个部分以丑陋的形式互相耦合:在一处修改数据,却在另一处造成难以发现的破坏。 |
意义 | |
定义 | |
做法 | |
注意 |
将引用对象改为值对象(Change Reference to Value)
title | content |
---|---|
场景 | 你有一个引用对象,很小且不可变,而且不易管理。 |
定义 | 将它变成一个值对象。 |
意义 | 我可以放心地把不可变的数据值传给程序的其他部分,而不必担心对象中包装的数据被偷偷修改。 我可以在程序各处复制值对象,而不必操心维护内存链接。 值对象在分布式系统和并发系统中尤为有用。 |
做法 | |
注意 |
将值对象改为引用对象(Change Value to Reference)
title | content |
---|---|
场景 | 你从一个类衍生出许多彼此相等的实例,希望将它们替换为同一个对象。 |
定义 | 将这个值对象变成引用对象 |
意义 | |
做法 | |
注意 |
以对象取代数据值(Replace Data Value withObject)
title | content |
---|---|
场景 | 你有一个数据项,需要与其他数据和行为一起使用才有意义 你有一个数组,其中的元素各自代表不同的东西 |
定义 | 将数据项变成对象。 |
意义 | |
做法 | 以对象替换数组,对于数组中的每个元素,以一个字段来表示。 |
注意 |
以字面常量取代魔法数(Replace Magic Number with SymbolicConstant)
title | content |
---|---|
场景 | 你有一个字面数值,带有特别含义。 |
定义 | 创造一个常量,根据其意义为它命名,并将上述的字面数值替换为这个常量。 |
意义 | 避免魔术数字 |
做法 | 集中定义同一业务相关的所有常量 |
封装集合(EncapsulateCollection)
title | content |
---|---|
场景 | 有个函数返回一个集合。 |
定义 | 让这个函数返回该集合的一个只读副本,并在这个类中提供添加/移除集合元素的函数。 |
意义 | 查询与处理分离 |
做法 | 新建类 |
以子类取代类型码(Replace Type Code withSubclass)
title | content |
---|---|
场景 | 有一个不可变的类型码,它会影响类的行为。 |
定义 | 以子类取代这个类型码。 |
意义 | 区分不同类型码的行为 |
做法 | ?状态机 |