在类与类之间搬移状态和行为,是重构过程中必不可少的步骤。很有可能在你现在觉得正常的类,等你到了下个礼拜你就会觉得不合适。或者你在下个礼拜创建了一个新的类并且你需要讲现在类的部分字段和行为移动到这个新类中。如果你发现在一个类中的某个字段,更多的被别的类的函数所使用,包括设值set和取值get函数锁取用,那么你就应该考虑搬移这个字段。当然,你也可能会去考虑是否使用Move Method去搬移这些使用这个字段的函数到这个字段的源类中去,这取决于你是否能够接受接口的变化,如果这些函数更加适合待在原地不动,那么你就应该选择Move Field。如果你此时需要将行为和字段都搬移出去出去形成一个新类(Extract Class),那么此时你应该先Move Field之后再Move Method。

做法:

  • 如果你需要搬移的字段是public级别的,你需要使用Encapsulate Field先将它封装起来。如果你可能需要移动那些频繁访问该字段的函数,或者有很多函数访问某个字段,那么Self Encapsulate Field可能对你有帮助。
  • 编译,测试。
  • 在目标类建立和源类相同的字段,并建立相应的设值和取值函数。
  • 编译目标类。
  • 决定如何在源对象中引用目标对象。首先查看是否有现成的字段或者函数可以取得目标对象,如果没有就尝试能不能建立一个这样的函数,如果还是不能,就考虑在源类新建一个字段来存放目标对象,这可能是永久性的修改,但也可能因为后续的重构你会把这个新建字段给删除。
  • 删除源字段。
  • 将所有对源字段的引用替换为对某个目标函数的调用。如果需要读取变量,就把对源字段的引用替换为对目标取值函数的调用,如果需要对变量赋值,就把对源字段的引用替换为对目标设值函数的调用。如果源字段不是private级别的,就必须在源类的所有子类中查找替换对源字段的引用,并进行替换。
  • 编译,测试。

例子:

class Account...
private:
AccountType m_type;
double m_interestRate;
public:
double interestForAmountdays(double amount, int days)
{
return m_interestRate * amount * days / ;
}

我想把m_interestRate移到AccountType中去,我们可以看到,interestForAmountdays这个函数已经引用了这个字段,接下来我们要做的就是在AccountType中建立同样的字段,并设置取值和设值函数

class AccountType...
private:
double m_interestRate;
public:
void setInterestRate(double arg)
{
m_interestRate = arg;
}
double interestRate() const
{
return m_interestRate;
}

添加完成后,我们对目标类进行编译。现在我们需要将源类中对原字段访问的函数转而使用对目标取值函数的调用,然后我们删除源类中的字段。删除源字段也可以让编译器帮我们查找出所有需要修改的函数。

double interesetForAmountdays(double amount, int days)
{
return m_type.interestRate() * amount * days / ;
}

这里演示的是单一函数存在对源字段的引用。如果这里有很多函数都对原字段进行过引用,我们可以先使用Self Encapsulate Field进行自我封装。

class Account...
private:
AccountType m_type;
double m_interestRate;
public:
double interesetForAmountdays(double amount, int days)
{
return interestRate() * amount * days / ;
} void setInterestRate(double arg)
{
m_interestRate = arg;
} double interestRate() const
{
return m_interestRate;
}

这个带来的好处就是当我们搬移字段中之后,我们不需要去追踪所有引用字段的函数,我们只需要去修改取值函数和设值函数就可以达到所有函数的修改。

double interesetForAmountdays(double amount, int days)
{
return interestRate() * amount * days / ;
} void setInterestRate(double arg)
{
m_type.setInterestRate(arg);
}
double interestRate() const
{
return m_type.interestRate();
}

当然,如果你也可以让这些调用访问函数的用户直接去访问目标对象。Self Encapsulate Field可以让你的重构进行小步伐前进,很有帮助。小步伐前进也是重构能够稳步前进的秘诀,可以让你的工作和生活变得更加轻松。特别值得一提的是,如果你一开始就使用Self Encapsulate Field,如果此时你需要使用Move Method,在这个函数中可能正好有对该字段的访问

double interesetForAmountdays(double amount, int days)
{
return interestRate() * amount * days / ;
}

他在Account类中,被你搬移到了AccountType中,因为你没有在函数里写成字段,而是写的取值函数,这意味着你这段函数即时到了AccountType中你也无需修改,你只需要对AccountType增加对应的取值函数interestRate()即可完成Move Method。

『重构--改善既有代码的设计』读书笔记----Move Field的更多相关文章

  1. 『重构--改善既有代码的设计』读书笔记----Move Method

    明确函数所在类的位置是很重要的.这样可以避免你的类与别的类有太多耦合.也会让你的类的内聚性变得更加牢固,让你的整个系统变得更加整洁.简单来说,如果在你的程序中,某个类的函数在使用的过程中,更多的是在和 ...

  2. 『重构--改善既有代码的设计』读书笔记----Extract Method

    在编程中,比较忌讳的一件事情就是长函数.因为长函数代表了你这段代码不能很好的复用以及内部可能出现很多别的地方的重复代码,而且这段长函数内部的处理逻辑你也不能很好的看清楚.因此,今天重构第一个手法就是处 ...

  3. 『重构--改善既有代码的设计』读书笔记----Extract Class

    在面向对象中,对于类这个概念我们应该有一个清晰的责任认识,就是每个类应该只有一个变化点,每个类的变化应该只受到单一的因素,即每个类应该只有一个明确的责任.当然了,说时容易做时难,很多人可能都会和我一样 ...

  4. 『重构--改善既有代码的设计』读书笔记----Inline Class

    如果某个类没有做太多的事情,你可以将这个类的所有特性搬移到另外一个类中,然后删除原类.可以看到,Inline Class正好和Extract Class相反,后者是将一个巨类分解成多个小类从而来分担责 ...

  5. 『重构--改善既有代码的设计』读书笔记----Change Value to Reference

    有时候你会认为某个对象应该是去全局唯一的,这就是引用(Reference)的概念.它代表当你在某个地点对他进行修改之后,那么所有共享他的对象都应该在再次访问他的时候得到相应的修改.而不会像值对象(Va ...

  6. 『重构--改善既有代码的设计』读书笔记----Replace Method with Method Object

    有时候,当你遇到一个大型函数,里面的临时变量和参数多的让你觉得根本无法进行Extract Method.重构中也大力的推荐短小函数的好处,它所带来的解释性,复用性让你收益无穷.但如果你遇到上种情况,你 ...

  7. 『重构--改善既有代码的设计』读书笔记---Duplicate Observed Data

    当MVC出现的时候,极大的推动了Model与View分离的潮流.然而对于一些已存在的老系统或者没有维护好的系统,你都会看到当前存在大把的巨大类----将Model,View,Controller都写在 ...

  8. 『重构--改善既有代码的设计』读书笔记----Replace Array with Object

    如果你有一个数组,其中的元素各自代表不同东西,比如你有一个 QList<QString> strList; 其中strList[0]代表选手姓名,strList[1]代表选手家庭住址,很显 ...

  9. 『重构--改善既有代码的设计』读书笔记----Self Encapsulate Field

    如果你直接访问一个字段,你就会和这个字段直接的耦合关系变得笨拙.也就是说当这个字段权限更改,或者名称更改之后你的客户端代码都需要做相应的改变,此时你可以为这个字段建立设值和取值函数并且只以这些函数来访 ...

随机推荐

  1. [转]让程序在崩溃时体面的退出之Unhandled Exception

    原文地址:http://blog.csdn.net/starlee/article/details/6613424 程序是由代码编译出来的,而代码是由人写的.人非圣贤,孰能无过.所以由人写的代码有缺陷 ...

  2. Calendar - SGU 115(日期判断)

    这年的开始的第一天是星期 1 代码如下: =============================================================================== ...

  3. java_method_readFile读取文件文本txt

    /** * @Title: TxtAndCsvUtils.java * @Package cn.com.qmhd.tools * @Description: TODO(读取txt和CSV文档) * @ ...

  4. ifndef系列

    文件中的#ifndef 头件的中的#ifndef,这是一个很关键的东西.比如你有两个C文件,这两个C文件都include了同一个头文件.而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了, ...

  5. IOS 多个ImageView图片层叠透明区域点击事件穿透

    经常用到多个透明图片层叠,但又需要获取不同图片的点击事件,本文实现图片透明区域穿透点击事件 实现人体各个部位点击 - (BOOL) pointInside:(CGPoint)point withEve ...

  6. 在命令行cmd 下,输入dxdiag 查看关于电脑许多硬件的详细信息

    输入命令就可以查看本机的很多硬件的详细信息: 在命令行cmd 下,输入dxdiag  查看关于电脑许多硬件的详细信息

  7. DB2 数据库绑定用户授权命令

    1.1  数据库绑定用户授权命令 db2 connect to opca db2 grant dbadm,createtab,bindadd,connect,create_not_fenced_rou ...

  8. 如何正确并完全安装Visual Studio 2015企业版本[转]

    http://blog.csdn.net/code_godfather/article/details/47381631 [注意事项]1> 本文描述的是: Visual Studio 2015企 ...

  9. [PWA] Enable Push Notification in your web app

    1. Clone the project: git clone https://github.com/GoogleChrome/push-notifications.git 2. install th ...

  10. hdoj Last non-zero Digit in N! 【数论】

    找规律! 求N!最后非0位的值.比方2是120的最后一个不是0的值. 输入N比較大,要大数保存. 注意到最后0的个数是与5的因数的个数相等.设f(n)为n!的最后非0位. 那么f(n)=((n%5)! ...