您的位置:知识库 » 软件设计

重构之美之一利用多态重构为带参方法

作者: 张逸  来源: 博客园  发布时间: 2010-12-05 17:51  阅读: 973 次  推荐: 0   原文链接   [收藏]  

   我在阅读遗留代码时,经常发现存在这样一种情形。在一个类中存在两个方法,它们做了相似的工作,区别仅在于方法内部某些对象的类型。例如:

public class WorkSheet{
private void fillHeader() {
Header header
= createHeader();
for (String title:header.getTitles()) {
fillCell(title);
}
}
Private
void fillBody() {
CellGroup cellGroup
= createCellGroup();
for (Cell cell:cellGroup.getCells()) {
fillCell(cell.getText());
}
}
}

  方法fillHeader()和fillBody()的目的都是从对象中获得字符串数组,然后将其填充到单元格中。区别在于,获得字符串数组的对象并不相同。前者为Header对象,后者为CellGroup对象。我们可以为其提供一个抽象的接口,以实现代码的有效重用:

public interface TextDataSource {
public String[] getTextArea();
}

  然后,让Header和CellGroup类均实现该接口。由于CellGroup并没有直接定义返回字符串数组的方法,而是通过返回的Cell对象获得text值,因此,需要将这部分实现封装到getTextArea()方法中:

public class Header implements TextDataSource {
@Override
public String[] getTextArea() {
//这里的实现即为原有的getTitles()实现
//可以保留原有的方法,并在本方法中指向该方法
//也可以利用Rename Method手法,直接更名该方法
}
}
public class CellGroup implements TextDataSource {
@Override
public String[] getTextArea() {
List
<String> textArea = new ArrayList<String>();
for (Cell cell:this.getCells()) {
textArea.add(cell.getText());
}
return textArea.toArray();
}
}

  现在,就可以重构原有的WorkSheet类了。

public class WorkSheet{
private void fillSheet(TextDataSource dataSource) {
for (String text:dataSource.getTextArea()) {
fillCell(text);
}
}
}

  具体需要填充什么内容,可以在调用fillSheet()方法时,根据传入的参数对象来决定。经过重构之后,WorkSheet类中的重复代码得到了移除,且具有了更好的扩展性。

  这一重构手法与Parameterize Method要解决的坏味道相似,同样对相似方法提取了共同的参数,但实现的本质完全不同。它利用了多态的原理,通过对抽象方法体中的相似对象,抹去了不同类型对象之间的差异性,使得方法体中的相似结构能够被抽取出来。

  我将这一重构手法命名为Parameterize Method by Polymorphism。让我仿照Martin Fowler的风格,给出这一重构方式的作法(Mechanics):
  1)新建一个接口,并使原有方法中的差异对象实现该接口。
  2)如果原有对象的方法与该接口定义的方法签名不同,则运用Rename Method。
  3)编译。
  4)新建一个参数为新接口类型的方法,使它可以替换先前所有的重复方法。
  5)编译。
  6)将对旧方法的调用替换为对新函数的调用。
  7)编译,测试。
  8)对所有旧方法重复上述步骤,每次替换后,修改并测试

  如果在调用新方法时,发现创建参数实参对象是一件麻烦事,可以考虑在原有类中引入一个创建新接口对象的工厂方法,从而对复杂的创建逻辑进行封装。

0
0
标签:重构

软件设计热门文章

    软件设计最新文章

      最新新闻

        热门新闻