在类与类之间搬移状态和行为,是重构过程中必不可少的步骤。很有可能在你现在觉得正常的类,等你到了下个礼拜你就会觉得不合适。或者你在下个礼拜创建了一个新的类并且你需要讲现在类的部分字段和行为移动到这个新类中。如果你发现在一个类中的某个字段,更多的被别的类的函数所使用,包括设值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. suse linux编译安装GCC报错

    gcc编译安装过程 1.先安装三个库 gmp mprc mpc 这三个库的源码要到官网去下载 1)安装gmp:首先建立源码同级目录 gmp-build,输入命令,第一次编译不通过,发现缺少一个叫m4的 ...

  2. Performance testing of web application

    Testing the performance of web application is easy . It's easy to design unrealistic scenario . Easy ...

  3. unity3d shader之God Ray上帝之光

    又是一个post-process后期效果,god ray 上帝之光,说起上帝之光就是咱们再看太阳时太阳周围一圈的针状光芒先放组效果,本文的场景资源均来自浅墨大神,效果为本文shader效果 加入了前篇 ...

  4. opengl performance optimization

    OpenGL 性能优化 作者: Yang Jian (jyang@cad.zju.edu.cn) 日期: 2009-05-04 本文从硬件体系结构.状态机.光照.纹理.顶点数组.LOD.Cull等方面 ...

  5. openstack 启用spice

    Openstack启用spice协议 #控制节点 #安装 ? 1 apt-get install nova-spiceproxy spice-html5 spice-vdagent #配置 nano ...

  6. zabbix 飞信集成配置

    1.环境说明: (Gentoo Linux环境) # uname -a Linux Crob 2.6.34-gentoo #1 SMP Mon May 31 15:45:25 CST 2010 x86 ...

  7. 广州Uber优步司机奖励政策(1月18日~1月24日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  8. c#语言基础编程-转义符

    C#转义字符: 引言 为了在程序中能够控制字符的输出以及区分开双引号和单引号(双引号和单引号在程序中标示里面的内容为字符串和字符),所以用一种特殊的字符常量:是·以反斜线"\"开头 ...

  9. UIView与CALayer的区别,很详细

    研 究Core Animation已经有段时间了,关于Core Animation,网上没什么好的介绍.苹果网站上有篇专门的总结性介绍,但是似乎原理性的东西不多,看得人云山雾罩,感觉,写那篇东西的人, ...

  10. 开源 免费 java CMS - FreeCMS2.1 会员站内信

    项目地址:http://www.freeteam.cn/ 站内信 1.1.1 写信 从左側管理菜单点击写信进入. 输入收信人.标题.内容后点击发送button. 1.1.2 收件箱 从左側管理菜单点击 ...