重构改善既有代码设计--重构手法18:Self Encapsulate Field (自封装字段)
你直接访问一个值域(field),但与值域之间的耦合关系逐渐变得笨拙。
为这个值域建立取值/设值函数(getting/setting methods),并且只以这些函数来访问值域。
private int _low, _high;
boolean includes(int arg) {
return arg >= _low && arg <= _high;
}
==〉
private int _low, _high;
boolean includes(int arg) {
return arg >= getLow() && arg <= getHigh();
}
int getLow() {return _low;}
int getHigh() {return _high;}
动机
如果你想访问superclass中的一个值域,却又想在subclass中将[对这个变量的访问]改为一个计算后的值,这就是最该使用Self Encapsulate Field(171)的时候。[值域自我封装]只是第一步。完成自我封装之后,你可以在subclass中根据自己的需要随意覆写取值/设值函数(getting/setting methods)。
作法
1. 为[待封装值域]建立取值/设值函数(getting/setting methods)。
2. 找出该值域的所有引用点,将它们全部替换为[对于取值/设值函数的调用]。
如果引用点是[读值]值域值,就将它替换为[调用取值函数];如果引用点是[设定]值域值,就将它替换为[调用设值函数]。
你可以暂时为设值域改名,让编译器帮助你查找引用点。
3. 将该值域声明为private。
4. 复查,确保找出所有引用点。
5. 编译,测试。
class IntRange {
private int _low, _high;
boolean includes(int arg) {
return arg >= _low && arg <= _high;
}
void grow(int factor) {
_high = _high * factor;
}
IntRange(int low, int high) {
_low = low;
_high = high;
}
}
为了封装_low和_high这两个值域,我先定义[取值/设值函数](如果此前没有定义的话),并使用它们:
class IntRange {
private int _low, _high;
boolean includes(int arg) {
return arg >= _low && arg <= _high;
}
void grow(int factor) {
SetHigh(getHigh()*factor);
}
int getLow() {
return _low;
}
int getHigh() {
return _high;
}
void setLow(int arg) {
_low = arg;
}
void setHigh(int arg) {
_high = arg;
}
}
使用本项重构时,一般说来,设值函数被认为应该在[对象创建后]才使用,所以初始化过程中的行为有可能与设值函数的行为不同。这种情况下,我允许在构造函数中直接访问值域,要不就是建立另一个独立的初始化函数:
IntRange(int low, int high) {
initialize(low, high);
}
private void initialize(int low, int high) {
_low = low;
_high = high;
}
一旦你拥有一个subclass,上述所有动作的价值就体现出来了。如下所示:
class CappedRange extends IntRange {
CappedRange(int low, int high, int cap) {
super(low, high);
_cap = cap;
}
private int _cap;
int getCap() {
return _cap;
}
int getHigh() {
return Math.min(super.getHigh(), getCap());
}
}
现在,我可以CappedRange class中覆写getHigh(),从而加入对cap的考虑,而不必修改IntRange class的任何行为。
重构改善既有代码设计--重构手法18:Self Encapsulate Field (自封装字段)的更多相关文章
- 重构改善既有代码设计--重构手法11:Move Field (搬移字段)
你的程序中,某个字段被其所驻类之外的另一个类更多的用到.在目标类建立一个新字段,修改源字段的所有用户,令它们改用新字段. 动机:在类之间移动状态和行为,是重构过程中必不可少的措施.随着系 ...
- 重构改善既有代码设计--重构手法16:Introduce Foreign Method (引入外加函数)&& 重构手法17:Introduce Local Extension (引入本地扩展)
重构手法16:Introduce Foreign Method (引入外加函数)你需要为提供服务的类增加一个函数,但你无法修改这个类.在客户类中建立一个函数,并以第一参数形式传入一个服务类实例. 动机 ...
- 重构改善既有代码设计--重构手法08:Replace Method with Method Object (以函数对象取代函数)
你有一个大型函数,其中对局部变量的使用,使你无法釆用 Extract Method. 将这个函数放进一个单独对象中,如此一来局部变量就成了对象内的值域(field) 然后你可以在同一个对象中将这个大型 ...
- 重构改善既有代码设计--重构手法07:Remove Assignments to Parameters (移除对参数的赋值)
代码对一个 参数赋值.以一个临时变量取代该参数的位置. int Discount(int inputVal, int quantity, int yearTodate) { if (input ...
- 重构改善既有代码设计--重构手法05:Introduce Explaining Variable (引入解释性变量)
发现:你有一个复杂的表达式. 解决:将该复杂的表达式(或其中的部分)的结果放进一个临时变量,并以此变量名称来解释表达式用途. //重构前 if((platform.toUpperCase().in ...
- 重构改善既有代码设计--重构手法04:Replace Temp with Query (以查询取代临时变量)
所谓的以查询取代临时变量:就是当你的程序以一个临时变量保存某一个表达式的运算效果.将这个表达式提炼到一个独立函数中.将这个临时变量的所有引用点替换为对新函数的调用.此后,新函数就可以被其他函数调用. ...
- 重构改善既有代码设计--重构手法02:Inline Method (内联函数)& 03: Inline Temp(内联临时变量)
Inline Method (内联函数) 一个函数调用的本体与名称同样清楚易懂.在函数调用点插入函数体,然后移除该函数. int GetRating() { return MoreThanfiveLa ...
- 重构改善既有代码设计--重构手法01:Extract Method (提炼函数)
背景: 你有一段代码可以被组织在一起并独立出来.将这段代码放进一个独立函数,并让函数名称解释该函数的用途. void PrintOwing(double amount) { PrintBanner() ...
- 重构改善既有代码设计--重构手法19:Replace Data Value with Object (以对象取代数据值)
你有一笔数据项(data item),需要额外的数据和行为. 将这笔数据项变成一个对象. class Order... private string customer; ==> class Or ...
随机推荐
- 团队Alpha冲刺(九)
目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:凯琳 组员6:翟丹丹 组员7:何家伟 组员8:政演 组员9:黄鸿杰 组员10:刘一好 组员11:何宇恒 展示 ...
- 项目Beta冲刺(团队)第二天
1.昨天的困难 夜间模式实现的时候一点击开关就会出现app黑屏卡死的状态,recreate()方法实现有问题 服务器有点问题 2.今天解决的进度 成员 进度 陈家权 研究如何实现私信模块 赖晓连 最新 ...
- DNS测试工具的使用(了解)
dig命令, host命令, nslookup命令,rndc命令 dig命令(直接测试DNS性能,不会查询/etc/hosts文件) dig [-t RR_TYPE] name [@SERVER] [ ...
- Windows连接Linux服务器中MySQL数据库-权限配置
问题描述 在Windows系统中安装了监控MySQL数据库服务器性能的工具Spotlight on MySQL,利用Spotlight连接Linux服务器中的MySQL,进行相关配置如下: 点击& ...
- c 用指针操作结构体数组
重点:指针自加,指向下一个结构体数组单元 #include <stdio.h> #include <stdlib.h> #include <string.h> #d ...
- Centos上Apache重启,mysql重启,nginx重启方法
转载:http://www.3lian.com/edu/2012/04-01/24278.html Centos上Apache重启,mysql重启, nginx 重启方法 1.重启 apache se ...
- sharepoint content type publishing
1. Create 1 Project Team sites (Site1) on SharePoint(可以用普通site)2. Go to http://<PCName>:8080/_ ...
- 【C++】构造函数不能是虚函数
1 虚函数对应一个vtable,这大家都知道,可是这个vtable其实是存储在对象的内存空间的.问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没 ...
- Spring Cloud Sleuth服务跟踪
监控 使用zipkin(https://zipkin.io/) 监控服务构建: (普通的springBoot项目) <!--引入的zipkinServer依赖--> <depende ...
- Android四大组件之contentProvider
Activity,Service,broadcast and Contentprovider android 4 大组件. ContentProvider:使用: public class Image ...