重构-改善既有代码的设计(四)----------在对象之间搬移特性
2017-02-07 17:31
423 查看
接下来的一系列文章我将写关于重构过程中具体的一些操作,今天 先来说比较重要的一点,就是在对象之间搬移特性。
对于java来这种面向对象的设计语言,“决定把责任放在哪里“即使不是最重要的事情,也是最重要的事情之一,我相信即使一个使用面向对象技术十几年的人也不一定在一开始就能保证做对,但是,不用担心,我们可以运用重构,改变自己原先的设计。
常常只需要用到Move Method 和Move Field 简单的移动对象行为,就可以解决这些问题,如果这两种重构方法都需要用到,我会首先使用Move Field,再使用Move Method。
类往往因为承担过多责任而变得臃肿不堪,这时,可以使用Extract Class 将一部分责任分离出去,如果一个类变得太不负责任,就可以用Inline Class(将类内联化)将它融入另一个类,如果一个类使用了另外一个类,运用Hide Delegate将这种关系隐藏起来通常是有帮助的,有时候隐藏委托类会导致拥有者的接口经常变化,此时需要使用Remove Middle Man。
还有两个比较特殊的重构方式,当我不能访问某个类的源码,但是又想把其他责任移进这个不可修改的类时,才会使用Introduce Foregin Method(引入外加函数) 和Introduce Local Extension(引入本地扩展),看到这里其实我也开始糊涂了,不过不要担心,后边会一一讲解具体实战应用,需要你做的事情就是坚持并一字不漏的看下去。go ahead。
4.1 Move Method(搬移函数)
情形:程序中有个函数与其所在类之外的另一个类进行更多交流:调用后者或者被后者所调用。
解决:在该函数最常引用的类中建立一个有着类似行为的新函数,将旧函数变成一个单纯的委托函数,或者将旧函数完全移除。
因为如果两个类因为太多合作而形成高度耦合,就可以通过这种手段,使各个类更简单,这些类也能更干净利落的实现系统交付的任务。所以我们要做的就是浏览类的所有函数,从中寻找这样的函数:使用另一个对象的次数币使用自己所在对象的次数还要多。一旦移动了一些字段,就要做这样的检查。一旦发现有可能搬移的函数,就会观察调用他的那一端,他调用的那一端,以及继承体系中他的任何一个重定义函数,然后根据“这个函数与哪个对象的交流比较多“决定其移动路径。
做法:
检查源类中被源函数所使用的一切特性(包括字段和函数),考虑他们是否也应该别搬移
检查源类的子类和超类,看看是否有该函数的其他声明
在目标类中声明这个函数
将源函数的代码复制到目标函数中,调整后,使其能在新家中正常运行
编译目标类
决定如何从源函数正确的引用目标对象
修改源函数,使之成为一个纯委托函数
编译测试,
决定是否删除源函数,活将它作为一个委托函数保留下来
如果要移除源函数,请将源类中对源函数的所有调用替换为目标函数的调用
4.2 Move Field(搬移字段)
情形:程序中,某个字段被其所在类之外的另一个类更多的用到
解决:在目标类新建一个字段,修改源字段的所有用户,令他们改用新字段
做法:
如果字段的访问级是public,使用Encapsulate Field(封装字段)将它封装起来
编译,测试
在目标类中建立与源字段相同的字段,并同时建立相应的设值/取值函数
编译目标类
决定如何在源对象中引用目标对象
删除源字段
将所有对源字段的引用替换为对某个目标函数的调用
编译,测试
4.3 Extract Class(提炼类)
情形:某个类做了本应该由两个类做的事情
解决:建立一个新类,将相关的字段和函数从旧类搬移到新类
理论上一个类应该清楚的处理一些明确的责任,但是实际开发中,我们一会在这加入一些功能,在哪加入一些数据,在给某个类添加一项新责任时,会觉得不值得为这项责任分离出一个单独的类,于是,随着责任的不断增加,这个类就会变得过分复杂,很快,这个类就容易变得一团乱麻。这样得类往往含有大量函数和数据而不容易被理解,此时需要考虑哪些部分可以分离出去到一个单独的类中,如果某些函数数据和某些函数总是一起出现,某些数据经常变化甚至彼此相依,这就表示你应该将他分离出去,一个有用的测试就是,如果你搬移了某些字段和函数,活发生什么事情,其他字段和函数是否因此变得毫无意义?
另一个就是开发后期类的子类化信号,如果你发现子类化只影响类的部分特性,或如果你发现某些特性需要以一种方式来子类化,某些方式要以另外一种形式子类化,这就意味着你需要分解原来的类。
做法:
决定如何分解类所负责的责任
建立一个新类,用以表现从旧类中分离出来的责任
建立“从旧类访问新类”的连接关系
对于你想搬移的每一个字段,运用Move Field搬移之
每次搬移以后,编译,运行
使用Move Method 将必要函数搬移到新类,先搬移较底层函数,再搬移较高层的函数
每次搬移以后,编译,测试
检查,精简每个类的接口
决定是否公开新类,如果需要公开,就要决定让它成为引用对象还是不可变的值对象
4.4 Inline Class (将类内联化)
情形:某个类没有做太多事情
解决:将这个类的所有特性搬移到另一个类中,然后移除原类
通常这个情形出现的原因是此前的重构动作移走了这个类的责任,一般会挑选这一“猥琐类”的最频繁用户,以Inline Class手法将之塞进另一个类中。
做法:
在目标类身上声明源类的public协议,并将其中所有函数委托至源类
修改所有源类引用点,改而引用目标类
编译,测试
运用Move Method 和Move Field 将源类的特性全部搬移到目标类
为
对于java来这种面向对象的设计语言,“决定把责任放在哪里“即使不是最重要的事情,也是最重要的事情之一,我相信即使一个使用面向对象技术十几年的人也不一定在一开始就能保证做对,但是,不用担心,我们可以运用重构,改变自己原先的设计。
常常只需要用到Move Method 和Move Field 简单的移动对象行为,就可以解决这些问题,如果这两种重构方法都需要用到,我会首先使用Move Field,再使用Move Method。
类往往因为承担过多责任而变得臃肿不堪,这时,可以使用Extract Class 将一部分责任分离出去,如果一个类变得太不负责任,就可以用Inline Class(将类内联化)将它融入另一个类,如果一个类使用了另外一个类,运用Hide Delegate将这种关系隐藏起来通常是有帮助的,有时候隐藏委托类会导致拥有者的接口经常变化,此时需要使用Remove Middle Man。
还有两个比较特殊的重构方式,当我不能访问某个类的源码,但是又想把其他责任移进这个不可修改的类时,才会使用Introduce Foregin Method(引入外加函数) 和Introduce Local Extension(引入本地扩展),看到这里其实我也开始糊涂了,不过不要担心,后边会一一讲解具体实战应用,需要你做的事情就是坚持并一字不漏的看下去。go ahead。
4.1 Move Method(搬移函数)
情形:程序中有个函数与其所在类之外的另一个类进行更多交流:调用后者或者被后者所调用。
解决:在该函数最常引用的类中建立一个有着类似行为的新函数,将旧函数变成一个单纯的委托函数,或者将旧函数完全移除。
因为如果两个类因为太多合作而形成高度耦合,就可以通过这种手段,使各个类更简单,这些类也能更干净利落的实现系统交付的任务。所以我们要做的就是浏览类的所有函数,从中寻找这样的函数:使用另一个对象的次数币使用自己所在对象的次数还要多。一旦移动了一些字段,就要做这样的检查。一旦发现有可能搬移的函数,就会观察调用他的那一端,他调用的那一端,以及继承体系中他的任何一个重定义函数,然后根据“这个函数与哪个对象的交流比较多“决定其移动路径。
做法:
检查源类中被源函数所使用的一切特性(包括字段和函数),考虑他们是否也应该别搬移
检查源类的子类和超类,看看是否有该函数的其他声明
在目标类中声明这个函数
将源函数的代码复制到目标函数中,调整后,使其能在新家中正常运行
编译目标类
决定如何从源函数正确的引用目标对象
修改源函数,使之成为一个纯委托函数
编译测试,
决定是否删除源函数,活将它作为一个委托函数保留下来
如果要移除源函数,请将源类中对源函数的所有调用替换为目标函数的调用
4.2 Move Field(搬移字段)
情形:程序中,某个字段被其所在类之外的另一个类更多的用到
解决:在目标类新建一个字段,修改源字段的所有用户,令他们改用新字段
做法:
如果字段的访问级是public,使用Encapsulate Field(封装字段)将它封装起来
编译,测试
在目标类中建立与源字段相同的字段,并同时建立相应的设值/取值函数
编译目标类
决定如何在源对象中引用目标对象
删除源字段
将所有对源字段的引用替换为对某个目标函数的调用
编译,测试
4.3 Extract Class(提炼类)
情形:某个类做了本应该由两个类做的事情
解决:建立一个新类,将相关的字段和函数从旧类搬移到新类
理论上一个类应该清楚的处理一些明确的责任,但是实际开发中,我们一会在这加入一些功能,在哪加入一些数据,在给某个类添加一项新责任时,会觉得不值得为这项责任分离出一个单独的类,于是,随着责任的不断增加,这个类就会变得过分复杂,很快,这个类就容易变得一团乱麻。这样得类往往含有大量函数和数据而不容易被理解,此时需要考虑哪些部分可以分离出去到一个单独的类中,如果某些函数数据和某些函数总是一起出现,某些数据经常变化甚至彼此相依,这就表示你应该将他分离出去,一个有用的测试就是,如果你搬移了某些字段和函数,活发生什么事情,其他字段和函数是否因此变得毫无意义?
另一个就是开发后期类的子类化信号,如果你发现子类化只影响类的部分特性,或如果你发现某些特性需要以一种方式来子类化,某些方式要以另外一种形式子类化,这就意味着你需要分解原来的类。
做法:
决定如何分解类所负责的责任
建立一个新类,用以表现从旧类中分离出来的责任
建立“从旧类访问新类”的连接关系
对于你想搬移的每一个字段,运用Move Field搬移之
每次搬移以后,编译,运行
使用Move Method 将必要函数搬移到新类,先搬移较底层函数,再搬移较高层的函数
每次搬移以后,编译,测试
检查,精简每个类的接口
决定是否公开新类,如果需要公开,就要决定让它成为引用对象还是不可变的值对象
4.4 Inline Class (将类内联化)
情形:某个类没有做太多事情
解决:将这个类的所有特性搬移到另一个类中,然后移除原类
通常这个情形出现的原因是此前的重构动作移走了这个类的责任,一般会挑选这一“猥琐类”的最频繁用户,以Inline Class手法将之塞进另一个类中。
做法:
在目标类身上声明源类的public协议,并将其中所有函数委托至源类
修改所有源类引用点,改而引用目标类
编译,测试
运用Move Method 和Move Field 将源类的特性全部搬移到目标类
为
相关文章推荐
- PHP 杂谈《重构-改善既有代码的设计》之二 对象之间搬移特性
- PHP 杂谈《重构-改善既有代码的设计》之二 对象之间搬移特性
- PHP 杂谈《重构-改善既有代码的设计》之二 对象之间搬移特性
- PHP 杂谈《重构-改善既有代码的设计》之二 对象之间搬移特性
- 重构—改善既有代码的设计007:在对象之间搬移特性(Moving Features Between Objects)
- 在对象之间搬移特性(读书摘要——重构改善既有代码的设计)
- PHP 杂谈《重构-改善既有代码的设计》之二 对象之间搬移特性【链接:http://www.cnblogs.com/baochuan/archive/2012/04/01/2427199.html】
- PHP 杂谈《重构-改善既有代码的设计》之二 对象之间搬移特性
- 重构改善既有代码的设计--在对象之间搬移特性
- PHP 杂谈《重构-改善既有代码的设计》之二 对象之间搬移特性
- 《重构--改善既有代码的设计》--在对象之间搬移特性(7)
- 重构改善既有代码的设计--在对象之间搬移特性
- 重构 改善既有代码的设计——在对象之间搬移特性
- 重构改善既有代码设计----- 在对象之间搬移特性
- 重构-改善既有代码的设计:对象之间移动特性的八种方法(五)
- 重构-改善既有代码的设计:对象之间移动特性的八种方法(五)
- 重构-改善既有代码的设计:对象之间移动特性的八种方法(五)
- 《重构》读书笔记(七)——第七章 在对象之间搬移特性
- 《重构改善既有代码的设计》之重构列表--在对象之间搬移特性(三)
- 改善代码设计 —— 优“.NET技术”化物件之间的特性(Moving Features Between Objects)