`
381895649
  • 浏览: 227776 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

java 代码重构-第一章(运用多态(Polymorphism)取代与价格相关的条件逻辑)

    博客分类:
  • java
阅读更多

上一篇文章:java 代码重构-第一章(去除临时变量)

 

 

继续吧...

运用多态(Polymorphism)取代与价格相关的条件逻辑

 

前述有些重构码系从上版本里头拷贝过来——主要是循环设置部分。更深入的重构动作可以清除这些重复代码。我可以把处理表头(header)、表尾(footer)和报表细目的代码都分别提炼目出来。在 Form Template Method 实例中,.你可以看到如何做这些动作。但是,现在用户又开始嘀咕了,他们准备修改影片分类规则。我们尚未清楚他们想怎么做,但似乎新分类法很快就要引入,现有的分类法马上就要变更。与之相应的费用计算方式和常客积点计算方式都还待决定,现在就对程序做修改,肯定是愚蠢的。我必须进入费用计算和常客积点计算中,把「因条件 而异的代码」(译注:指的是switch 语句内的case 子句)替换掉,这样才能为 将来的改变镀上一层保护膜。现在,请重新戴回「重构」这顶帽子。

这个问题的第一部分是switch 语句。在另一个对象的属性(attribute)基础上运用switch 语句,并不是什么好主意。如果不得不使用,也应该在对象自己的数据上使用,而不是在别人的数据上使用。

看java代码

 

class Rental...
  double getCharge() {
      double result = 0;
      switch (getMovie().getPriceCode()) {
          case Movie.REGULAR:
              result += 2;
              if (getDaysRented() > 2)
                  result += (getDaysRented() - 2) * 1.5;
              break;
          case Movie.NEW_RELEASE:
              result += getDaysRented() * 3;
              break;
          case Movie.CHILDRENS:
              result += 1.5;
              if (getDaysRented() > 3)
                  result += (getDaysRented() - 3) * 1.5;
              break;
      }
      return result;
 }

 

 这暗示getCharge() 应该移到Movie class 里头去:

 

class Movie...

  double getCharge(int daysRented) {
      double result = 0;
      switch (getPriceCode()) {
          case Movie.REGULAR:
              result += 2;
              if (daysRented > 2)
                  result += (daysRented - 2) * 1.5;
              break;
          case Movie.NEW_RELEASE:
              result += daysRented * 3;
              break;
          case Movie.CHILDRENS:
              result += 1.5;
              if (daysRented > 3)
                  result += (daysRented - 3) * 1.5;
              break;
      }
      return result;
  }

 为了让它得以运作,我必须把「租期长度」作为参数传递进去。当然,「租期长度」来自收Rental 对象。计算费用时需要两份数据:「租期长度」和「影片类型」。为什么我选择「将租期长度传给Movie 对象」而不是「将影片类型传给Rental 对象」呢?因为本系统可能发生的变化是加入新影片类型,这种变化带有不稳定倾向。如果影片类型有所变化,我希望掀起最小的链滴,所以我选择在Movie 对象内计算费用。

 

 

我把上述计费方法放进Movie class 里头,然后修改Rental 的getCharge(),让它使用这个新函数(图1.12和图1.13):

 

 

 

class Rental...
  double getCharge() {
      return movie.getCharge(_daysRented);
  }

 搬移getCharge() 之后,我以相同手法处理常客积点计算。这样我就把根据影片类型而变化的所有东西,都放到了影片类型所属的class 中。

 

 

以下是重构前的代码:

 

class Rental...
 int getFrequentRenterPoints() {
     if ((getMovie().getPriceCode() == Movie.NEW_RELEASE) && getDaysRented() > 1)
        return 2;
     else
        return 1;
 }

 重构如下:

 

Class rental..
 int getFrequentRenterPoints() {
     return movie.getFrequentRenterPoints(_daysRented);
 }

class movie...
 int getFrequentRenterPoints(int daysRented) {
     if ((getPriceCode() == Movie.NEW_RELEASE) && daysRented > 1)
         return 2;
     else
        return 1;
}
  • 大小: 22.5 KB
  • 大小: 22.1 KB
1
3
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics