简化函数调用之七 :Preserve Whole Object(保持对象完整)
来源:互联网 发布:联合办公网络设计方案 编辑:程序博客网 时间:2024/06/06 19:51
你从某个对象中取出若干值,将它们作为某一次函数调用时的参数。
改使用(传递)整个对象。
int low = daysTempRange().getLow();
int high = daysTempRange().getHigh();
withinPlan = plan.withinRange(low, high);
withinPlan = plan.withinRange(daysTempRange());
动机(Motivation)
有时候,你会将来自同一对象的若干项数据作为参数,传递给某个函数。这样做的问题在于:万一将来被调用函数需要新的数据项,你就必须查找并修改对此函数的所有调用。如果你把这些数据所属的整个对象传给函数,可以避免这种尴尬的处境, 因为被调用函数可以向那个参数对象请求任何它想要的信息。
除了可以使参数列更稳固(不变动)之外,Preserve Whole Object 往往还能提高代码的可读性。过长的参数列很难使用,因为调用者和被调用者都必须记住这些参数的用途。此外,不使用完整对象也会造成重复代码,因为被调用函数无法利用完整对象中的函数来计算某些中间值。
「甘蔗不曾两头甜」!如果你传的是数值,被调用函数就只与这些数值有依存关系(dependency),与这些数值所属对象没有任何依存关系。但如果你传递的是整个对象,「参数对象」和「被调用函数所在对象」之间,就有了依存关系。如果这会使你的依存结构恶化,那么你就不该使用Preserve Whole Object。
我还听过另一种不使用Preserve Whole Object 的理由:如果被调用函数只需要「参数对象」的其中一项数值,那么只传递那个数值会更好。我并不认同这种观点,因为传递一项数值和传递一个对象,至少在代码清晰度上是等价的〔当然对于pass by value(传值)参数来说,性能上可能有所差异)。更重要的考量应该放在「对象之间的依存关系」上。
如果被调用函数使用了 [来自另一个对象的很多项数据」,这可能意味该函数实际上应该被定义在「那些数据所属的对象」中。所以,考虑Preserve Whole Object 的同时,你也应该考虑Move Method。
运用本项重构之前,你可能还没有定义一个完整对象。那么你就应该先使用Introduce Parameter Object。
还有一种常见情况:调用者将自己的若干数据作为参数,传递给被调用函数。这种情况下,如果该对象有合适的取值函数(getter),你可以使用取代这些参数值,并且无须操心对象依存问题。
作法(Mechanics)
范例:(Example)
以下范例,我以一个Room 对象表示「房间」,它负责记录房间一天中的最高温度和最低温度。然后这个对象需要将「实际温度范围」与预先规定的「温度控制计划」 相比较,告诉客户当天温度是否符合计划要求:
class Room...
boolean withinPlan(HeatingPlan plan) {
int low = daysTempRange().getLow();
int high = daysTempRange().getHigh();
return plan.withinRange(low, high);
}
class HeatingPlan...
boolean withinRange (int low, int high) {
return (low >= _range.getLow() && high <= _range.getHigh());
}
private TempRange _range;
其实我不必将TempRange 对象的信息拆开来单独传递,只需将整个对象传递给withinPlan() 函数即可。在这个简单的例子中,我可以一次性完成修改。如果相关的参数更多些,我也可以进行小步重构。首先,我为参数列添加新的参数项,用 以传递完整的TempRange 对象:
class HeatingPlan...
boolean withinRange (TempRange roomRange, int low, int high) {
return (low >= _range.getLow() && high <= _range.getHigh());
}
class Room...
boolean withinPlan(HeatingPlan plan) {
int low = daysTempRange().getLow();
int high = daysTempRange().getHigh();
return plan.withinRange(daysTempRange(), low, high);
}
然后,我以TempRange 对象提供的函数来替换low 参数:
class HeatingPlan...
boolean withinRange (TempRange roomRange, int high) {
return (roomRange.getLow() >= _range.getLow() && high <= _range.getHigh());
}
class Room...
boolean withinPlan(HeatingPlan plan) {
int low = daysTempRange().getLow();
int high = daysTempRange().getHigh();
return plan.withinRange(daysTempRange(), high);
}
重复上述步骤,直到把所有待处理参数项都去除为止:
class HeatingPlan...
boolean withinRange (TempRange roomRange) {
return (roomRange.getLow() >= _range.getLow() &&roomRange.getHigh() <= _range.getHigh());
}
class Room...
boolean withinPlan(HeatingPlan plan) {
int low = daysTempRange().getLow();
int high = daysTempRange().getHigh();
return plan.withinRange(daysTempRange());
}
现在,我不再需要low 和high 这两个临时变量了:
class Room...
boolean withinPlan(HeatingPlan plan) {
int low = daysTempRange().getLow();
int high = daysTempRange().getHigh();
return plan.withinRange(daysTempRange());
}
使用完整对象后不久,你就会发现,可以将某些函数移到TempRange 对象中,使它更容易被使用,例如:
class HeatingPlan...
boolean withinRange (TempRange roomRange) {
return (_range.includes(roomRange));
}
class TempRange...
boolean includes (TempRange arg) {
return arg.getLow() >= this.getLow() && arg.getHigh() <= this.getHigh();
- 简化函数调用之七 :Preserve Whole Object(保持对象完整)
- Preserve Whole Object(保存对象完成)
- 简化函数调用之九 :Introduce Parameter Object(引入参数对象)
- 简化条件表达式之七 :Introduce Null Object(引入Null 对象)
- 简化函数调用(一)
- 简化函数调用(二)
- 简化函数调用(三)
- 简化函数调用之二 :Add Parameter(添加参数)
- 重构之简化函数调用
- 重构方法之简化函数调用
- 重构之简化函数调用
- 重构系列之对象行为的重构:《重构》简化函数调用
- Object-C--->Swift之(七)函数重载
- 简化函数调用
- 5、简化函数调用
- 简化函数调用
- 简化函数调用之五 :Parameterize Method(令函数携带参数)
- 简化函数调用之六 :Replace Parameter with Explicit Methods(以明确函数取代参数)
- 什么是面向对象(1)
- pb使用msxml进行网页存取
- DROP DATABASE ORA-01504
- JAVA形参值传递,引用传递分析。
- 生成 guid 字符串化
- 简化函数调用之七 :Preserve Whole Object(保持对象完整)
- UIColor使用colorWithRed定义颜色
- 0032算法笔记——【回溯法】电路板排列问题和连续邮资问题
- 备份注册表操作
- JSP常见的指令有哪些?(面试必备)
- 简化函数调用之八 :Replace Parameter with Method(以函数取代参数)
- A. Life Without Zeros
- Java开发中的23种设计模式详解
- H264中I帧与IDR帧区别