博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
重构手法之在对象之间搬移特性【1】
阅读量:4985 次
发布时间:2019-06-12

本文共 3884 字,大约阅读时间需要 12 分钟。

本小节目录

1Move Method(搬移函数)

概要

你的程序中,有个函数与其所驻类之外的另一个类进行更多交流:调用后者,或被或者调用。

在该函数最常引用的类中建立一个有着类似行为的新函数。将旧函数变成一个单纯的委托函数,或是将旧函数完全移除。

动机

如果一个类有太多行为,或如果一个类与另一个类有太多合作而形成高度耦合,又或者使用另一个对象的次数比使用自己所驻对象的次数还多。那就要搬移函数。

搬移函数时,要根据“这个函数与哪个对象的交流比较多”来决定其移动路径。

范例

用一个表示“账户”的Account类来说明这项重构:

class Account{    private AccountType _accountType;    private int _daysOverdrawn;    ///     /// 透支金额计费规则    ///     /// 
double OverdraftCharge() { if (_accountType.IsPremium()) { double result = 10; if (_daysOverdrawn > 7) { result += (_daysOverdrawn - 7) * 0.85; } return result; } return _daysOverdrawn * 1.75; } double BankCharge() { double result = 4.5; if (_daysOverdrawn > 0) { result += OverdraftCharge(); } return result; }}

AccountType类如下:

class AccountType{       public bool IsPremium()       {            return true;       } }

假设有几种新账户,每一种都有自己的“透支金额计费规则”。所有我们将OverdraftCharge()搬移到AccountType类去。

首先要做的就是:观察OverdraftCharge()使用的每一项特性,考虑是否值得将它们与OverdraftCharge()一起移动。此例中,我们需要让_daysOverdrawn 字段留在Account类中,因为这个值不会随着不同种类的账户而变化。然后我们将OverdraftCharge()函数代码复制到AccountType中,并做相应调整。

class AccountType{    public double OverdraftCharge(int daysOverdrawn)    {        if (IsPremium())        {            double result = 10;            if (daysOverdrawn > 7)            {                result += (daysOverdrawn - 7) * 0.85;            }            return result;        }        return daysOverdrawn * 1.75;    }    public bool IsPremium()    {        return true;    }}

然后将源函数的函数本体替换为一个简单的委托动作。

class Account{
/// /// 透支金额计费规则 /// ///
double OverdraftCharge() { return _accountType.OverdraftCharge(_daysOverdrawn); }}

重构到这里就可以结束了。当然了,我们也可以删除Account中的源函数。我们找到源函数的所有调用者,并将这些调用重新定向,改为调用Account的BankCharge()。

class Account{    private AccountType _accountType;    private int _daysOverdrawn;      double BankCharge()    {        double result = 4.5;        if (_daysOverdrawn > 0)        {            result += _accountType.OverdraftCharge(_daysOverdrawn);        }        return result;    }}

此例中被搬移函数只引用了一个字段,所以只需将这个字段作为参数传给目标函数就行了。如果被搬移函数调用了Account中的另一个函数,可以将源对象传递给目标函数。

class AccountType{    public double OverdraftCharge(Account account)    {        if (IsPremium())        {            double result = 10;            if (daysOverdrawn > 7)            {                result += (account.GetDaysOverdrawn() - 7) * 0.85;            }            return result;        }        return account.GetDaysOverdrawn()* 1.75;    }    public bool IsPremium()    {        return true;    }}

 小结

在搬移函数时,检查源类中被源函数所使用的一切特性,考虑它们是否也该被搬移。如果某个特性只被你打算搬移的那个函数用到,那就应该将它一并搬移。如果另有其他函数使用了这个特性,就可以考虑将使用该特性的所有函数全都一并搬移。

2Move Field(搬移字段)

概要

在你的程序中,某个字段被其所驻类之外的另一个类更多地用到。

在目标类建立一个字段,修改源字段的所有用户,令它们改用新字段。

动机

在类之间移动状态和行为,是重构中必不可少的措施。随着系统的发展,我们会发现自己需要新的类,并需要将现有的工作责任拖到新的类中。

对于一个字段,在其所驻类之外的另一个类中有更多函数使用了它,就要考虑搬移这个字段。

范例

还是以Account类为例。

class Account{    private AccountType _accountType;    private double _interestRate;    double GetInterestForAmountByDays(double amount, int days)    {        return _interestRate * amount * days / 365;    }}

我们想要把_interestRate搬移到AccountType类中去。目前已经有数个函数引用了它,GetInterestForAmountByDays()就是其中之一。

我们在AccountType中建立一个_interestRate字段,并封装成属性。

class AccountType{    private double _interestRate;    public double InterestRate    {        get => _interestRate;        set => _interestRate = value;    }}

现在让Account类中访问的_interestRate字段的函数转而使用AccountType对象,并且删除Account类中的_interestRate字段。

class Account{    private AccountType _accountType;    double GetInterestForAmountByDays(double amount, int days)    {        return _accountType.InterestRate * amount * days / 365;    }}

小结

对于C#来说,可能这个重构手法叫“搬移属性”更合适一点。因为基本上字段都是私有的,属性才是供其他函数访问的。搬移属性做法和范例中是一样的。

 

To Be Continued……

转载于:https://www.cnblogs.com/liuyoung/p/7858062.html

你可能感兴趣的文章
Spring Cloud Eureka 使用 IP 地址进行服务注册
查看>>
Python 包的制作(__init__.py)
查看>>
java内存模型优化建议
查看>>
三十、模块补充
查看>>
流程审批设计
查看>>
别装了,你根本就不想变成更好的人
查看>>
数据库 join
查看>>
AES加密工具类[亲测可用]
查看>>
方法区
查看>>
Django-----ORM
查看>>
ARCGIS部分刷新
查看>>
发 零 食
查看>>
poj3613:Cow Relays(倍增优化+矩阵乘法floyd+快速幂)
查看>>
洛谷P1886 滑动窗口
查看>>
Shell编程(二)Bash中调用Python
查看>>
主动与被动监控 拓扑图组合图 自定义监控
查看>>
SQL总结(一)基本查询
查看>>
PDF分割--可脱离python环境执行,可传参数,可弹窗的PC端小工具
查看>>
cas-client-core单点登录排除不需要拦截的URL
查看>>
OCR技术浅探 : 文字定位和文本切割(2)
查看>>