当你无法获得一个类的源代码或者没有权限去修改这个类的时候,你对于这种为你服务的类,你可能会出现需要别的需求的时候,比如一个Date类,你需要能够让他本身直接返回出他的后一天的对象,但他没有,这个时候你就需要暂时使用Introduce Foreign Method来做过渡,并且在适当时候通知作者把这个Foreign Method搬移到他所属于的自己的类中去。

这种情况其实也很多,特别是当你在团队当中,当有别人写了一个类的时候,你会去利用这个类去做你想要做的事情,但如果你发现这个类并没有提供你所要的功能,如果你可以去修改源代码,那当然可以。你可以直接在类的源代码中增加一行你所想要的功能。但如果你不能获取源代码,你就只能在客户端编码,补充你所想要的那个函数。

当然,如果你所处的客户类只使用这项功能一次,那没什么大不了,你可以完全额外添加多出来的处理逻辑。甚至你可能都不需要原来提供服务的那个对象本身,但是,如果你需要多次去使用这个函数,你就不得不去重复这些代码,还记得吗

重复代码是软件的万恶之源。

这些重复代码应该被抽出来运用Extract Method放进同一个函数中去,当然如果你迫不得已执行本次重构,这也给了你一个明确的信号:这个函数原本应该在提供服务的类中实现。

如果你发现自己已经为一个服务类增加的大量函数,或者发现有许多类都需要同样的外加函数,你就不应该再使用本次重构,而应该使用Introduce Local Extension。但是请不要忘记,Foreign Method始终是权宜之计,如果有可能,你仍然应该将这些函数通过Move Method搬移到他们的理想家园。如果你无法进行这样的搬移,你也可以把这个外加函数交给服务类的拥有者,请他帮你在服务类中实现这个函数。

做法:

  • 在客户类中建立一个函数,用来提供你需要的功能。这个函数不应该调用客户类的任何特性,如果他需要一个值,把值当作传输传给他,而不是让他在函数内部本身去调用你客户类的特性。在这里有一个技巧,为了避免之前说的那种可能会让你提炼的函数引用客户类的特性,我们可以在新创建的函数给他static特性,大家都知道C++的static会迫使你不能去接触所属类的特性。
  • 以服务类实例作为这个函数的第一个参数。
  • 将该函数注释为“foreign method应该在服务类中实现”来提醒你将来有机会将外加函数搬移道服务类中的时候可以很快速的找到这些函数。

例子:

Date newStart = new Date(perviousEnd.getYear(), perviousEnd.getMonth(), perviousEnd.getDate()
+ );

在例子中我们可以看到,我在客户端代码里需要一个跨越一个收费周期的函数,但实际Date并不提供这个函数,所以我只能自己写一个冗长的new。当然,如果出现一处这种地方我们不需要太在意,但是如果出现多出,我们就需要使用Extract Method进行重构,这个函数就是Date类的外加函数。我们可以这么声明

Date newStart = nextDay(perviousEnd);

static Date nextDay(Date arg)
{
// foreign method, should be on Date
return new Date(arg.getYear(), arg.getMonth(), arg.getDate()
+ );
}

可以看到,我们让这个函数变成static这样可以保证我们不使用客户端类的任何特性,同时我们把这个函数的第一个参数作为服务类对象传进,这样我们以后在进行Move Method的时候可以得到无参化的简洁接口。

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

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

    同Introduce Foreign Method一样,很多时候你不能修改编辑原始类,你需要为这些服务类增加一些额外的函数,但你没有这个权限或者入口.如果你只需要一个或者两个外加函数那么你可以放心的使 ...

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

    有时候你会遇到一系列复杂的表达式连续运算的时候,这个时候你可能根本招架不住如此长或者是如此复杂的长函数.这个时候你可以通过引用临时变量来储存他们的结果,将这些长函数的结果分成一个个临时变量来让函数清晰 ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. HDU-2522 A simple problem

    http://acm.hdu.edu.cn/showproblem.php?pid=2522 学习://除数的运算的应用和算法.除法的本质,如果余数出现重复就表示有循环节 A simple probl ...

  2. Android学习笔记(七)两个Fragment简单跳转示例

    在前两篇博文中分别介绍了Fragment得基础和Fragment的生命周期,然而说了这么多Fragment到底怎么用呢以及我们为什么要使用Fragment?本篇博文将主要探讨这两个问题,首先说下在AP ...

  3. tyvj P1864 [Poetize I]守卫者的挑战(DP+概率)

    P1864 [Poetize I]守卫者的挑战 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 打开了黑魔法师Vani的大门,队员们在迷宫般的路上漫无目的地搜 ...

  4. UVa 10917 A Walk Through the Forest

    A Walk Through the Forest Time Limit:1000MS  Memory Limit:65536K Total Submit:48 Accepted:15 Descrip ...

  5. 介绍两个Eclipse插件: Implementors & Call Hierarchy

    介绍两个Eclipse插件: Implementors & Call Hierarchy 本文介绍两个在Eclipse调试与跟踪过程中的两个实用插件 他们都可以在 http://eclipse ...

  6. zabbix_fetion_alter

  7. 如何将下载好的jar包添加到maven本地仓库

    1.首先在pom.xml中添加 <dependency>    <groupId>org.springframework.security</groupId>    ...

  8. zy 送画

    问题描述 话说在军训的倒数第二天,zy终于下定决心要将画了 10天之久的画像送给他心怡的法学院mm.但是,他不敢自己一个人去,倒霉的 kk 只能和他一起去了.不过,为了表现的有诚意,kk和zy不能走在 ...

  9. java.lang.RuntimeException: Missing type parameter

    程序中用到了gson的new typeToken,结果打包成apk发布时,发现抛出异常,但不通过打包apk时发现一切正常,百思不得其解,最初怀疑没有将gson-1.7.1.JAR打包进去,后来经过测试 ...

  10. shell获取 linux 系统的位数

    getconf LONG_BIT 直接返回  32  或者 64