重构手段

1. 重新组织函数

重构手段动机做法
Extract Method(110)
提炼函数
1.函数粒度小更容易复用
2.高层函数就像一系类注释
3.函数粒度细,函数覆盖更容易
Inline Method(117)
内联函数
1.一个和Extract Method相反的用法,每个函数其内部代码和函数名名称一样清晰易读
2.如果小函数划分混乱的时候,也可以应该方法先合并为大函数,再拆分小函数。记住,并不是所有间接层都有价值
1.观察是否有多态
2.找出这个函数的所有被调用点
3.找出这个函数的所有被调用点都替换为函数本体
Inline Temp(119)
内联临时变量
1.Resplace Temp with Query 的一部分
2.发现某个临时变量被赋予某个函数的返回值
1.最好先将该变量声明为final,然后编译,确保临时变量只被赋之过一次值
Replace Temp whith Query(120)
以查询替代临时变量
临时变量只能在所属函数内使用,它会处使你写更长的函数 1.找出赋值一次的临时变量
2.将变量声明为final
3.编译
4.将“对临时赋值”之后的右侧部分提炼得到一个独立对的函数中
5.编译、测试
6.在变量的实施Inline Temp
Introduce Explaining Variable(124)
引入解释性变量
1.表达式过于复杂,引入解释变量提升可读性
2.为Extract Method 、Replace Temp with Query和 Replace Method with Mehod Oject梳理逻辑
Splite Temporary Variable(128)
分解临时变量
每个临时变量有各种不同的作用,保证变量的单一赋值
Remove Assignments to Parameters(131)
移除对参数的赋值
对参数赋值通常意味着副作用
substitute Algorithm(139)
替换算法
如果你发现一件事有更简单的、更清晰点的方式。就应该以比较清晰的方式取代复杂的方式

2. 在对象之间搬移特性

重构手段动机做法
Move Method(142)
搬移函数
1.一个类有太多行为,或者与另一个类有太多合作形成高度耦合
2. 寻找这样的函数,使用另一个对象的次数比自己所驻对象的次数还多
1.检查类中的被元函数所使用的一起特性(包括字段和函数),考虑一起搬移
2.检查源类的子类和超类是否有该函数的其他声明(若存在,目标类也表现出多态,不然无法搬迁
3.在目标类中声明这个函数,也可以重新命名
4.编译目标类
5.决定如何从源函数正确引用目标类
6.修改源函数,使之成为一个纯委托函数
7.编译,测试
8.决定是否删除源函数,或将它当做一个委托函数保留下来
9.将源类中对源函数的所有调用者替换为目标函数的调用
10.编译,测试
Move Field(146)
搬移字段
1.一个字段,在其所驻的类之外的另一个类中更多函数使用它,也可能set和get函数,间接依赖。
2. 移动字段还是函数?取决于移动该字段的用户(某个使用该字段的函数),这取决于是否需要保持接口不变
1.如果字段的访问级别是public使用Encapsulate Field(206)封装字段将它封装起来
2.如果有可能移动那些频繁访问字段的函数,或如果有多个函数范文字段,优先使用Self Encapsulate Field(1171)自封装字段
Extract Class(149)
提取类
类会不断成长,不断的加入一些字段,加一些方法
2. 如果某些数据和方法一起出现,某些数据经常同时变化甚至彼此依赖,这就表示你应该将他们分离出去
3. 后期开发出现的信号是子类化的方式。如果子类子化只影响类的部分功能,或者你发现某些特性需要一种子类化,某些特性需要另一种子类化
1.分解类的职责
2.新建类,以表现从旧类中分离出来
Inline Class(154)
将类内联化
与Extract Class 相反,一个类没有足够的职责,或者重构移走了字段和方法
Hide Delegate(157)
隐藏委托关系
XXXXXXXXXXXXXX
Remove Middle Man(160)
移除中间人
XXXXXXXXXXXXXX

3 重新组织数据

重构手段动机做法
Self Encapsulate Field(171)
自封装字段
使用setter和getter,访问和写字段
Replace Data value with Object(175)
以对象取代数据值
开发初期可能只需要一个字段,后期面对这个数据不简单了
Change value to Reference(179)
改变值对象为引用
确保对一个对象的修改作用到所有引用此对象的地方
Change reference Reference to Value (183)
改变值对象为引用
引用对象必须以某种方式控制,你总是必须向控制着请求适当的引用对象,可能造成内存全区域之间错综复杂
Replace Array with Object (186)
以对象替换数组
一个数组里面存放了同种类的数据,这时应考虑使用对象替换数组
Duplicate Observed Data (189)
复制“被监控数据”
将界面与业务分离,同时同步相关数据:1.有助于维护和开发;2.两种职责会使类更加复杂 引入观察者模式
Change Unidirectional Association to Bidirectional (197)
将单项关联该为双向关联
两个类之间建立一条单向对的引用链,一个类可以引用另一个类,随着时间推移,你发现需要被引用的类需要得其引用者,进行处理,也就是一个反向指针 1.在被引用类中,新加一个字段,用于保持引用指针
2.确定控制关联-有顶哪个类是引用端还是被引用端
Change Unidirectional Association to Bidirectional (197)
将单项关联该为双向关联
两个类之间建立一条单向对的引用链,一个类可以引用另一个类,随着时间推移,你发现需要被引用的类需要得其引用者,进行处理,也就是一个反向指针 1.在被引用类中,新加一个字段,用于保持引用指针
2.确定控制关联-有顶哪个类是引用端还是被引用端
3.在被控端建立一个辅助函数,其命名应该清楚指出2它的有限用途
4.xxxxxxxxxxxxxxxxx
Change Bidirectional Association to Unidirectional (200)
将双向关联该为单项关联
xxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxx
Replace magic number with Symbolic Constant (204)
使用字面常量取代魔法数
Encapsulate Field (206)
封装字段
Encapsulate Collection (208)
封装集合
1.直接返回集合的引用,客户修改了集合的引用,集合拥有者一万无所知
2.不应该为集合提够一个设置函数
1.返回集合本身是,应使用Collections.unmodifableSet等去包装。
Replace Type Code with Class (218)
以类取代类型码
1.任何接受类型码作为参数的函数,期望的实际是一个数值,无法强制使用符号名,这会打打降低代码的可读性
2.把数值替换一个类,在编译期间对对对类型检查们可以保证参数合法时,实例才会被创建出来
3.保证类型码是纯粹的数据时(不应在switch的等语句中)
Replace Type Code with SubClass (223)
以子类取代类型码
1.类型码不影响宿主类的行为时,可以使用Replace Type code with Class,那么最好的办法借助多态来实现
2.有两种情况不能使用:(1).类型值在对象创建了以后发生了变化(2).宿主类已经有了子类。这两只情况下,可以使用Replace Type code with State/Strategy
3.宿主类出现了“只具备特定类型码之对象相关的特性”。在此之后,可以继续使用Push Down Method(328)和push down Field(329)将这些特性推到子类中
Replace Type Code with State/Strategy (227)
以State/strategy取代类型码
1.如果“类型码的值在对象生命中发生变化”或其他宿主类不能被继承
2.如果采用此方法重构后,采用Replace Condition with Polymorphism(255)简化一个算法,那么选择Strategy比较合适
3.如果你打算搬移状态相关的数据,把新建的对象视为一种变迁状态,就应该选择使用state模式
xxxxxxxxxxxxxxxxxxxxxxxx
Replace SubClass whith Field (232)
以字段取代子类
子类存在,只提够个别硬编码的常量的功能,应该消除子类,在超类中,新建字段替换
Replace SubClass whith Field (232)
以字段取代子类
子类存在,只提够个别硬编码的常量的功能,应该消除子类,在超类中,新建字段替换

4 简化条件表达式

重构手段动机做法
Decompose Conditional(238)
分解表达式
Consolidate Conditional(240)
合并条件表达式
1.检查同一目的和结果。2.为Extract Mehod做准备
Consolidate Duplicate Conditional Fragments(243)
合并重复的条件片段
不同分支都执行了相同的某段代码,把重复代码合并
Remove Control Flag(245)
移除控制标记
代码中加入讨厌的控制标志符,编程语言提够break和continue就是跳出复杂的表达式
Replace Nested Conditional with Guard clauses(250)
以卫语句取代嵌套条件表达式
多层嵌套,通常意味着特殊处理,这时恰好与卫语句的定义一致,如果使用if-else通常表示分支同样重要
Replace Conditional with Polymorphism(250)
以多态替代条件表达式
同一个组条件表达式在程序许多地点出现,那么采取多态收益最大。
Introduce Null Object(260)
引入Null对象
xxxxxxxxxxxxxxx
Introduce Assertion(267)
引入断言
当某一块代码,只有某个条件为真是该段代码茶能正常运行,需要断言检查

5 简化函数调用

重构手段动机做法
Rename Method(273)
函数改名
当你无法给函数其一个好名字,立即修改其名字
Add Parameter(275)
添加参数
当你无法给函数其一个好名字,立即修改其名字
Add Parameter(275)
添加参数
Remove Parameter(277)
移除参数
separate Query from Modifier(279)
将查询函数和修改函数分离
即有返回值又有副作用的函数,将其拆解为一个查询和一个修改的函数
Parameterize Method(283)
令函数携带参数
若干函数做了类似的工作,但在函数本体中包含了不同的值,以参数粒度划分不同功能
Replace Parameter with Explicit Method(285)
已明确函数取代参数
以方法粒度划分不同功能
Preserve Whole Object(288)
保持对象完整
1.参数过长
2.提高可读性
Replace Parameter with Method(292)
以函数取代参数
xxxxxxxxxxxxxxxxxx
Introduce Parameter Object(295)
引入参数对象
Remove Setting Object(300)
移除设值函数
Hide method(300)
隐藏函数
吧函数设置为private
Replace Constructor with Factory Method(304)
以工厂函数取代构造函数
xxxxxxxxxxxxxxxx
Encapsulate Downcast(308)
封装向下转型
java是强类型语言,你必须告诉编译器确切的类型。
Replace Error Code with Exception(310)
以异常取代错误码
已经可以清晰表达"普通程序"和"错误处理"分开
Replace Exception with Test(315)
以测试代替异常
异常不可以取代条件检查

6 处理概括关系

处理继承的关系。

重构手段动机做法
Pull Up Field(320)
字段上移
子类字段重复,将字段移动到超类
Pull Up Method(322)
函数上移
1.子类中函数相同或者覆盖后与超类函数一致
2.被提升的函数引用了只出现在子类的函数,可以将这个函数一起提到超类
3.如果函数相似,可以先借助From Template Method(345)
Pull Up Construct Body(325)
构造函数本体上移
1.子类构造有共同的行为,第一念头就是将共同行为提炼到一个独立函数中
Pull Down Method(328)
函数下移
超类中的某个函数只与部分子类有关
Pull Down Filed(329)
字段下移
超类中的某个字段只与部分子类有关
Extract Subclass (330)
提炼子类
类中的某些特性只被某些实例用到
Extract Superclass (336)
提炼超类
两个类以相同的方式做类似的事情,对象提够了一种简化方式--继承
Extract Interface (341)
提炼接口
与Extract Superclass相比。1.每个类只有一个超类2.对职责更清晰3.依赖更清晰
Collapse Hierarchy (344)
折叠继承关系
子类化并未带来价值
Form Template Method (345)
塑造模板函数
两个函数以相同顺序执行大致相近的操作,但不完全相同,将执行顺序移至超类,并借助多态保证各种操作保证差异性
Replace Inheritance with Delegation (352)
以委托取代继承
从超类继承了一堆不需要的成员或函数
Replace Delegation with Inheritance (355)
以继承取代委托
1.受委托的所有函数和字段都使用了,应该用继承取代委托
2.受托对象的所有字段方法没有被调用,就不能采取此方法
3.受托对象不止一个请其他对象共享,而且受委托对象时可以变的,就不能采取此方法

参考

《重构-改善既有代码的设计》Martin Fowler

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值