到处都是重复的代码?方法体又臭又长看不懂?快来试试抽取方法(Extract Method)吧,保证药到病除!
何为抽取方法
将重复的代码或语义独立的代码抽取成一个方法
看好了:
Tom抓Jerry(又臭又长版)
class Tom {
/**
* Tom当前的位置
**/
private int curPos;
public void catchJerry() {
//只要没抓到Jerry就一直抓
while(true) {
//找Jerry
//左看看
int posOfJerry = lookLeft();
//右看看
if(posOfJerry == -1)
posOfJerry = lookRight();
//上看看,下看看
//.....省略
//前往Jerry的位置
while(curPos <= posOfJerry) {
//迈前腿
curPos++;
//迈后腿 保持平衡
//....
}
//抬起爪子
upHands();
//挥爪
Object objInHand = waveHands();
//Jerry是否在手中
if(Jerry.equals(objInHand))
break;
}
}
}
又臭又长,两个While的嵌套循环,让人不明所以,连走路迈腿都写在一块,如果没有注释的话,绝对让人无法理解
接下来见证重构的奇迹
简化逻辑:抓Jerry = 抓不到Jerry就一直抓
public void catchJerry() { //只要没抓到Jerry就一直抓 while(!tryCatchJerry()); }
catchJerry()只有一行了,此处应有掌声
但是我们又创建了又臭又长的方法——试图抓住Jerry
private boolean tryCatchJerry() { //找Jerry //左看看 int posOfJerry = lookLeft(); //右看看 if(posOfJerry == -1) posOfJerry = lookRight(); //上看看,下看看 //.....省略 //前往Jerry的位置 while(curPos <= posOfJerry) { //迈前腿 curPos++; //迈后腿 保持平衡 //.... } //抬起爪子 upHands(); //挥爪 Object objInHand = waveHands(); //Jerry是否在手中 return Jerry.equals(objInHand)); }
分而治之:试图抓住Jerry = 找Jerry + 前往Jerry位置 + 挥爪抓住Jerry
private boolean tryCatchJerry() { //找Jerry并前往Jerry的位置 go(findPosOfJerry()); //挥爪抓Jerry return waveHandsCatchSomething(Jerry); }
好的,tryCatchJerry简单又清晰了
我对剩下的方法进行了微调,让它们更有逻辑感
private int findPosOfJerry() { //左看看 int posOfJerry = lookLeft(); if(posOfJerry != -1) return posOfJerry; //右看看 posOfJerry = lookRight(); if(posOfJerry != -1) return posOfJerry; //上看看,下看看 //.....省略 } private void go(int pos) { while(curPos <= pos) { //迈前腿 curPos++; //迈后腿 保持平衡 //.... } } private boolean waveHandsCatchSomething(Object something) { //抬起爪子 upHands(); //挥抓,然后看看指定东西是否在手中 return something.equals(waveHands()); }
新版Tom抓Jerry
铛铛!掌声在哪里?
class Tom {
/**
* Tom当前的位置
**/
private int curPos;
public void catchJerry() {
//只要没抓到Jerry就一直抓
while(!tryCatchJerry());
}
private boolean tryCatchJerry() {
//找Jerry并前往Jerry的位置
go(findPosOfJerry());
//挥爪抓Jerry
return waveHandsCatchSomething(Jerry);
}
private int findPosOfJerry() {
//左看看
int posOfJerry = lookLeft();
if(posOfJerry != -1)
return posOfJerry;
//右看看
posOfJerry = lookRight();
if(posOfJerry != -1)
return posOfJerry;
//上看看,下看看
//.....省略
}
private void go(int pos) {
while(curPos <= pos) {
//迈前腿
curPos++;
//迈后腿 保持平衡
//....
}
}
private boolean waveHandsCatchSomething(Object something) {
//抬起爪子
upHands();
//挥抓,然后看看指定东西是否在手中
return something.equals(waveHands());
}
}
何时应该抽取方法
有重复代码
方法体又臭又长看不懂
怎么抽取方法
IDEA提供了重构的快捷方式和快捷键,使用IDEA进行重构,方便又快捷
- 选中要抽取的代码
- 进行方法抽取 右键->选择重构->抽取->方法 (或者直接使用快捷键Ctrl + Alt + m)
自动检测出个别重复代码的细微差别,有些代码可能只改动一两个变量,IDEA会自动检测出来,并在抽取方法时提醒我们,选择左侧Accept Signature Change(接受签名变动)可以使抽取的方法自动替换更多的重复点
可以选择替换掉所有的重复代码(竟然有18处)
重构——更改方法签名
如果你对抽取出的方法的名字、参数、返回值或是修饰符不满意,不要使用Ctrl + R 修改,IDEA提供了重构方法——更改签名(快捷键Ctrl + F6)
注意:方法的名字指的是方法做了什么,而非怎么去做,最好是 动词+名词 格式
比如:Tom.扫地() √
Tom.扫地With扫把() ×
Tom.用扫把扫地() ×
更多重构手段
等我把这些文章全写完发了,再给你们提供链接
- 抽取方法
到处都是重复的代码?方法体又臭又长看不懂?快来试试抽取方法(Extract Method)吧,保证药到病除!
- 使用对象封装参数集
答应我,别再给方法弄一长溜的参数了,好吗?
- 使用查询方法取代临时变量
你这方法里怎么这么多临时变量?我完全记不住每个变量是用来干什么的!
- 使用多态取代switch分支
“来看看外包老哥写的超长switch语句”这种文章又登上首页了
- 及时打断if条件分支
外包老哥总是被黑的幕后黑手找到了!
- 转移成员变量和函数
道理我都懂,可是你一直在用的成员变量为什么要让我负责管理?
- 抽取类
总觉得,是时候new一个替身出来帮我干活了
- 将数据的处理函数转移给持有数据的类
或许,这个锅应该由你来背
- 向父类转移成员变量和函数
所有子类都需要做的事,为什么不让父类直接做了?
- 注意集合型成员变量的get/set方法!
有人动了我的集合对象,可是我却不知道!
技术不分领域,思想一脉相承,欢迎访问橙味菌的博客