ivaneeo's blog

自由的力量,自由的生活。

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  669 Posts :: 0 Stories :: 64 Comments :: 0 Trackbacks
范例(Examples)
我用一个表示[帐户]的account class来说明这项重构:
class Account...
    double overdraftCharge() {   //透支金计费,它和其他class的关系似乎比较密切。
       if(_type.isPremium()) {
          double result = 10;
          if(_daysOverdrawn > 7)
             result += (_daysOverdrawn -7) * 0.85;
          return result;
       }
       else return _daysOverdrawn * 1.75;
    }
    double bankCharge() {
       double result = 4.5;
       if(_daysOverdrawn > 0) result += overdraftCh你arge();
       return result;
    }
    private AccountType _type;
    private int _daysOverdrawn;

假设有数种新帐户,每一种都有自己的[透支金计费规则]。所以我希望将overdraftCharge()搬移到AccountType class去。

第一步要做的是:观察被overdraftCharge()使用的每一特性(features),考虑是否值得将它们与overdraftCharge()一起移动。此例之中我需要让_daysOverdrawn值域留在Account class,因为其值会随不同种类的帐户而变化。然后,我将overdraftCharge()函数码拷贝到AccountType中,并做相应调整。
class AccountType...
    double overdraftCharge(int daysOverdrawn) {
       if(isPremium()) {
          double result = 10;
          if(daysOverdrawn >7)
             result += (daysOverdrawn - 7) * 0.85;
          return result;
        }
       else return daysOverdrawn * 1.75;
    }
在这个例子中,[调整]的意思是:(1)对于[使用AccountType特性]的语句,去掉──type;(2)想办法得到依旧需要的Account class特性。当我需要使用source class特性,我有四种选择:(1)将这个特性也移到target class;(2)建立或使用一个从target class到source的引用(指涉)关系;(3)将source object当作参数传给target method;(4)如果所需特性是个变量,将它当作参数传给target method。

本例中我将_daysOverdrawn变量作为参数传给target method(上述(4))。

调整target method使之通过编译,而后我就可以将source method的函数本体替换为一个简单的委托动作(delegation),然后编译并测试:
    class Account...
       double overdraftCharge() {
          return _type.overdraftCharge(_daysOverdrawn);
       }
我可以保留代码如今的样子,也可以删除source method。如果决定删除,就得找出source method的所有调用者,并将这些调用重新定向,改调用Account的bankCharge():
bankCharge():
    class Account...
       double bankCharge() {
          double result = 4.5;
          if(_daysOverdrawn > 0)
             result += _type.overdraftCharge(_daysOverdrawn);
          return result;
        }
所有调用点都修改完毕后,我就可以删除source method在Account中的声明了。我可以在每次删除之后编译并测试,也可以一次性批量完成。如果被搬移的函数不是private,我还需要检查其 他classes是否使用了这个函数。在强型(strongly typed)语言中,删除source method声明式后,编译器帮我发现任何遗漏。

此例之中被移函数只取用(指涉)一个值域,所以我只需将这个值域作为参数传给target method就行了。如果被移函数调用了Account中的另一个函数,我就不能这么简单地处理。这种情况下我必须将source object传递给target method:
class AccountType...
    double overdraftCharge(Account account) {
       if(isPremium()) {
          double result = 10;
          if(account.getDaysOverdrawn() >7)
             result += (account.getdaysOverdrawn() - 7) * 0.85;
          return result;
        }
       else return daysOverdrawn * 1.75;
    }
如果我需要source class的多个特性,那么我也会将source object传递给target method。不过如果target method需要太多source class特性,就得进一步重构。通常这种情况下我会分解target method,并将其中一部分移回source class。
posted on 2005-08-30 11:08 ivaneeo 阅读(221) 评论(0)  编辑  收藏 所属分类: refactoring-从地狱中重生

只有注册用户登录后才能发表评论。


网站导航: