手把手教你重构!-Refactor
回页首
回页首
就像所有的 Eclipse 重构操作一样,当您指定了全部用来执行重构的必要信息之后,您就可以点击?Preview?按钮,然后在一个对话框中对比 Eclipse 打算进行哪些变更,您可以分别否决或者确认每一个受到影响的文件中的每一项变更。如果您对于 Eclipse 正确执行变更的能力有信心的话,您可以只按下?OK按钮。显然,如果您不确定重构到底做了什么事情,您就会想先预览一下,但是对于 Rename 和 Move 这样简单的重构而言,通常没有必要预览。
Move 操作与 Rename 十分相似:您选择某个 Java 元素(通常是一个类),为其指定一个新位置,并定义是否需要更新引用。然后,您可以选择?Preview检查变更情况,或者选择?OK?立即执行重构,如图2所示。
图 2. 将类从一个包移到另一个包?
在某些平台上(特别是 Windows),您还可以在 Package Explorer 视图中通过简单拖放的方法将类从一个包或者文件夹中移到另一个包或文件夹中。所有的引用都会自动更新。
在按过?OK按钮之后,?motor
?属性以及?getMotor()?
和?setMotor()
?方法就会移动到?Automobile
?类中。清单7显示了在进行了这次重构之后?Automobile
?类的情形。
点击 OK 之后,接口就创建好了,如清单8所示。
使用父类的需求在 Java 语言中经常出现,特别是在使用了 Factory Method 模式的情况下。这种模式的典型实现方式是创建一个抽象类,其中具有静态方法?create()
?,这个方法返回的是实现了这个抽象类的一个具体对象。如果需创建的具体对象的类型依赖于实现的细节,而调用类对实现细节并不感兴趣的情况下,可以使用这一模式。
接下来,在第二次调用?st.nextToken()?
的地方重复进行重构,这一次调用的是一个新的局部变量?value
?。清单10显示了这两次重构之后代码的情形。
点击?OK之后,?Automobile?类中的?make
?属性就变成了私有属性,也同时具有了?getMake()?
和?setMake()?
方法。
第一个选项是改变该方法的可见性。在本例中,将其改变为 protected 或者 private,这样第二个类的?callTest()?
方法就不能访问这个方法了。(如果这两个类在不同的包中,将访问方法设为缺省值也会引起这样的问题。) Eclipse 在进行重构的时候不会将这些问题标出,您只有自己选择适当的值。
下面一个选项是改变返回值类型。如果将返回值改为?float
?,这不会被标记成错误,因为?test()?
方法返回语句中的?int
?会自动转换成?float
?。即便如此,在第二个类的?callTest()
方法中也会引起问题,因为?float
?不能转换成?int
?。您需要将?test()?
的返回值改为?int
?,或者是将?callTest()?
中的?r?
改为?float
?。
如果将第一个参数的类型从?String
?变成?int
?,那么也得考虑相同的问题。在重构的过程中这些问题将会被标出,因为它们会在被重构的方法内部引起问题:?int?
不具有方法?length()
。然而如果将其变成?StringBuffer
?,问题就不会标记出来,因为?StringBuffer?
的确具有方法?length()
?。当然这会在?callTest()?
方法中引起问题,因为它在调用?test()?
的时候还是把一个?String
?传递进去了。
前面提到过,在重构引发了问题的情况下,不管问题是否被标出,您都可以一个一个地修正这些问题,以继续下去。还有一种方法,就是先行修改这些错误。如果您打算删除不再需要的参数?i
?,那么可以先从要进行重构的方法中删除对它的引用。这样删除参数的过程就更加顺利了。
最后一件需要解释的事情是 Default Value 选项。这一选项值仅适用于将参数加入方法签名中的情况。比方说,如果我们加入了一个类型为?String?
的参数,参数名为?n
?,其缺省值为?world
?,那么在?callTest()?
方法中调用?test()?
的代码就变成下面的样子:
结束语
Eclipse 提供的工具使重构变得简单,熟悉这些工具将有助于您提高效率。敏捷开发方法采用迭代方式增加程序特性,因此需要依赖于重构技术来改变和扩展程序的设计。但即便您并没有使用要求进行正式重构的方法,Eclipse 的重构工具还是可以在进行一般的代码修改时提供节约时间的方法。如果您花些时间熟悉这些工具,那么当出现可以利用它们的情况时,您就能意识到所花费的时间是值得的。