『重构--改善既有代码的设计』读书笔记----Self Encapsulate Field
如果你直接访问一个字段,你就会和这个字段直接的耦合关系变得笨拙。也就是说当这个字段权限更改,或者名称更改之后你的客户端代码都需要做相应的改变,此时你可以为这个字段建立设值和取值函数并且只以这些函数来访问字段。
自古以来,面向对象关于字段访问就存在两个派系,其中一个派系认为,如果在该字段所在的类中,你就可以自由访问他,不需要通过间接的函数来获得。另外一派认为,即使在这个类中你也应该只使用设值和取值函数来间接访问。
当然了,间接访问可以带来的额外好处就是你可以通过子类来覆写函数做到改变获取数据的途径。他还可以让你支持灵活的数据管理方式,比如延迟初始化等。直接访问变量的好处也有,就是可以让我们阅读代码的人给我们更加明确清晰的思路,不要追函数追到一般才发现这原来只是一个简单的取值函数,从而影响我们的判断。
在面对这种选择的时候,我支持作者的观点,我在该字段本类中我会优先去使用直接访问的形式,直到这种直接访问的形式给我带来麻烦的时候,此时我才会去选择改变才用间接访问的方式,这也是重构带给我们的魅力,他可以让我们自由改变我们需要的方式。
如果你想访问超类中的一个字段,却又想在子类中对这个变量的访问改为一个计算后的值(或者针对那种简单的类型码判断,基类和子类返回不一样的类型码)这就是使用Self Encapsulate Filed的时候,字段自我封装只是第一步,完成自我封装之后,你可以在子类中根据自己的需要随意覆写取值/设值函数。
做法:
- 为待封装字段建立设值/取值函数。
- 找出该字段的所有引用点,将他们全部改为设值/取值函数。如果引用点要读取字段值,就将他改为调用取值函数。如果引用点要给字段,就将他改为设值函数。当然这里也有一个小技巧帮你可以更快更全的找到所有引用点,就是你通过对字段改名,借助编译器帮你找到所有这些引用点。
- 将该字段声明为private.
- 复查,确保找到所有引用点。
- 编译,测试。
例子:
class IntRange
{
public:
IntRange(int low, int high) :
m_low(low),
m_high(high)
{
} bool includes(int arg)
{
return arg >= m_low && arg <= m_high;
} void grow(int factor)
{
m_high = m_high * factor;
}
private:
int m_low;
int m_high;
}
为了封装m_low和m_high我们定义取值/设值函数,并使用它们。
class IntRange
{
public:
IntRange(int low, int high) :
m_low(low),
m_high(high)
{
} bool includes(int arg)
{
return arg >= low() && arg <= high();
} void grow(int factor)
{
m_high = m_high * factor;
} virtual int low() const
{
return m_low;
} virtual int high() const
{
return m_high;
}
private:
int m_low;
int m_high;
};
同时这里有一点需要注意的就是你的取值函数和设值函数如果是在构造函数中进行调用的你就需要注意,现在C++默认在构造函数中是不会呈现多态性的,也就是说如果你在基类的构造函数中放了一个虚函数,当你创建子类的时候,当进入到基类的构造函数的时候并不会去调用子类的虚函数,依然还是去调用基类的虚函数。
同时还需要注意的就是默认一般来说,设值函数被认同是在对象创建之后才使用的,所以初始化过程中的行为可能与设值函数行为不同,这种情况下,你要么就是在构造函数中直接访问字段,要么就是单独创建另一个初始化函数。
IntRange(int low, int high) :
m_low(low),
m_high(high)
{
initialize(low, high);
} void initialize(int low, int high)
{
m_low = low;
m_high = high;
}
当然,现在你也许看不到什么价值,但如果你一旦拥有了子类,上述体现的价值就出来了。
class CappedRange : public IntRange
{
public:
CappedRange(int low, int high, int cap) :
IntRange(low, high),
m_cap(cap)
{
} virtual int cap() const
{
return m_cap;
} virtual int high() const
{
return qMin(IntRange::high(), cap());
} private:
int m_cap;
};
现在你可以在high()中进行覆写,从而加上范围上限的考虑而不必修改IntRange的任何行为。
『重构--改善既有代码的设计』读书笔记----Self Encapsulate Field的更多相关文章
- 『重构--改善既有代码的设计』读书笔记----Extract Method
在编程中,比较忌讳的一件事情就是长函数.因为长函数代表了你这段代码不能很好的复用以及内部可能出现很多别的地方的重复代码,而且这段长函数内部的处理逻辑你也不能很好的看清楚.因此,今天重构第一个手法就是处 ...
- 『重构--改善既有代码的设计』读书笔记---Duplicate Observed Data
当MVC出现的时候,极大的推动了Model与View分离的潮流.然而对于一些已存在的老系统或者没有维护好的系统,你都会看到当前存在大把的巨大类----将Model,View,Controller都写在 ...
- 『重构--改善既有代码的设计』读书笔记----Move Field
在类与类之间搬移状态和行为,是重构过程中必不可少的步骤.很有可能在你现在觉得正常的类,等你到了下个礼拜你就会觉得不合适.或者你在下个礼拜创建了一个新的类并且你需要讲现在类的部分字段和行为移动到这个新类 ...
- 『重构--改善既有代码的设计』读书笔记----Change Value to Reference
有时候你会认为某个对象应该是去全局唯一的,这就是引用(Reference)的概念.它代表当你在某个地点对他进行修改之后,那么所有共享他的对象都应该在再次访问他的时候得到相应的修改.而不会像值对象(Va ...
- 『重构--改善既有代码的设计』读书笔记----Replace Method with Method Object
有时候,当你遇到一个大型函数,里面的临时变量和参数多的让你觉得根本无法进行Extract Method.重构中也大力的推荐短小函数的好处,它所带来的解释性,复用性让你收益无穷.但如果你遇到上种情况,你 ...
- 『重构--改善既有代码的设计』读书笔记----Replace Array with Object
如果你有一个数组,其中的元素各自代表不同东西,比如你有一个 QList<QString> strList; 其中strList[0]代表选手姓名,strList[1]代表选手家庭住址,很显 ...
- 『重构--改善既有代码的设计』读书笔记----Move Method
明确函数所在类的位置是很重要的.这样可以避免你的类与别的类有太多耦合.也会让你的类的内聚性变得更加牢固,让你的整个系统变得更加整洁.简单来说,如果在你的程序中,某个类的函数在使用的过程中,更多的是在和 ...
- 『重构--改善既有代码的设计』读书笔记----Replace Data Value with Object
当你在一个类中使用字段的时候,发现这个字段必须要和其他数据或者行为一起使用才有意义.你就应该考虑把这个数据项改成对象.在开发初期,我们对于新类中的字段往往会采取简单的基本类型形式来保存,但随着我们开发 ...
- 『重构--改善既有代码的设计』读书笔记----Substitute Algorithm
重构可以把复杂的东西分解成一个个简单的小块.但有时候,你必须壮士断腕删掉整个算法,用简单的算法来取代,如果你发现做一件事情可以有更清晰的方式,那你完全有理由用更清晰的方式来解决问题.如果你开始使用程序 ...
随机推荐
- Linux下的各种软件安装方法汇总
1 RPM包 1.1 安装 RPM包就像Windows的EXE安装文件一样,各种文件都已经编译好了,并进行了打包,哪一个文件应该放在哪一个目录下都指定好了,安装非常方便,在图形界面里你只需要双击就能自 ...
- Cogs 1070. [焦作一中2012] 玻璃球游戏 带权并查集,逆序处理
题目: http://cojs.tk/cogs/problem/problem.php?pid=1070 1070. [焦作一中2012] 玻璃球游戏 ★ 输入文件:marbles.in 输出 ...
- 应用360云盘与SVN版本管理服务器搭建基于云端的版本控制软件
步骤一:(安装软件) 1.TortoiseSVN 2.VisualSVN-Server-2.71 3.安装云盘客户端360wangpan_setup 步骤二:(VisualSVN Server设置) ...
- js实现table中前端搜索(模糊查询)
项目中用到js前端搜索功能,根据 姓名或姓名 进行 搜索,实现方法如下,遍历table所有行中的某列,符合条件则置tr为display:'',不满足条件置tr为display:none. 代码如下: ...
- 搜狗输入法皮肤安装 分类: windows常用小技巧 2014-05-04 15:10 172人阅读 评论(0) 收藏
第一步: 下载皮肤,皮肤是.ssf格式的. 第二步: 找到安装目录:(以我的为例) D:\软件\搜狗输入法\SogouInput\7.1.0.1652\AllSkin: 把下载的皮肤剪切(或复制)到此 ...
- 【BZOJ1833】【ZJOI2010】数字计数 数位DP
链接: #include <stdio.h> int main() { puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网 ...
- node.js 安装
http://my.oschina.net/zhangdapeng89/blog/52793 windows 自带的 ims文件安装后 有 安装npm 点击bat文件可自动安装 npm 1安装 nod ...
- [PWA] Keynote: Progressive Web Apps across all frameworks
PWA: Add to home screen Angular Universal Server side rendering: for achieving better proference on ...
- Swift学习笔记八:枚举
1. 枚举语法 1)枚举的定义 使用enum关键词而且把它们的整个定义放在一对大括号内: enum SomeEumeration { // enumeration definition go ...
- 走进 Facebook POP 的世界
POP: 一个流行的可扩展的动画引擎iOS,它支持spring和衰变动态动画,使其可用于构建现实,基于物理交互.Objective - C API允许快速集成, 对于所有的动画和过渡他是成熟的. 解释 ...