1、重复代码
避免这种情况,采用提炼方法
void print(double amount){
printBanner();
System.out.println("name"+name);
System.out.println("amount"+amount);
}
更改为
void print(double amount){
printBanner();
printDetails(amount);
}
void printDetails(double amount){
System.out.println("name"+name);
System.out.println("amount"+amount);
}
如果是两个互为兄弟的子类内含相同表达式,可以使用函数上移
2、过长函数
使用提炼函数,会把许多参数和临时变量作为参数,可以使用以查询取代临时变量,如:
double price=quantily*item;
if(price>10)
return price*3;
else
return price*4;
改为
double price(){
return quantily*item;
}
if(price()>10)
return price*3;
else
return price*4;
为了过长的参数变得简洁还有使用引入参数对象
还可以使用保存对象完整
最后如果还是有许多参数和临时变量,使用以函数对象取代函数
将这个函数放进一个单独对象,这样局部变量就成了对象内的字段,然后你可以在同一对象中将这个大型函数进行分解成小函数
3、过大的类
使用提炼新类
使用提炼子类
4、过长参数列
以函数取代参数,让参数接受者去除该项参数,并直接调用前一个函数
int price= quantily*item;
disLevel=getDisLevel();
double finalPrice=disPrice(price,disLevel);
改为
int price= quantily*item;
double finalPrice=disPrice(price);
还可以使用保存对象完整和引入参数对象
5、发散式变化
如果某个类经常因为不同的原因在不同的方向上发生变化,也是使用提炼新类,上面已经提过,不再重复
6、霰弹式修改
如果需要修改的代码散补四处,会很难找到它们,也容易忘记某个重要的修改
这时候使用搬移函数
和搬移字段
如果没有合适的类安置这些代码,可以使用将类内联化
7、依恋情节
有时候我们会看到某个函数为了计算某个值,从另一个对象调用几乎半打的取值函数,这个时候可以使用搬移函数,如果函数中只有一部分依赖,那就使用提炼函数,判断原则:哪个类拥有最多被此函数使用的数据,然后就把这个函数和那些数据摆在一起
8、数据泥团
首先找出这些数据以字段形式出现的地方,然后使用提炼类将它们提炼到一个独立对象,然后使用引入参数对象和保存对象完整为其减肥,这样可以将很多参数列缩短,简化函数调用
9、基本类型偏执
使用以对象代替数据值
如果想要替换的数据值是类型码,可以使用以类取代类型码
一般使用对象代替
10、switch惊悚现身
switch语句的问题在于重复,可以使用多态概念解决
首先使用提炼函数将switch语句提炼到一个独立函数,然后使用搬移函数将它搬移到需要多态性的那个类,这个需要决定使用以子类取代类型码还是以State/Stragegy取代类型码(如果类型码会影响宿主类的行为,就使用后者)
例子:将类型码都替换成子类,有点像工厂方法
改变为
一旦完成了继承结构,就可以使用以多态取代条件表达式,使用条件表达式时,如果你想添加一种新的类型,就必须查找并更新所有条件表达式,但是用了多态,只需要建立一个新的子类,并在其中提供适当的函数就行,这减低系统各部分之间的依赖
11、平行继承体制
这种情况就是:每当你为某个类增加一个子类,必须也为另一个类相应增加一个子类
消除这种重复性可以使用让一个继承体制的实例去引用另一个继承体制的实例。还可以使用搬移函数和搬移字段
12、冗赘类
如果某些子类没有做足够的工作,可以使用折叠继承体制
对于几乎没用的组件,使用将类内联化
13、夸夸其谈未来性
这种情况就是:感觉未来会做某种事而企图以各种方式的钩子和特殊情况来处理一些非必要的事情
1、如果某个抽象类没有太大的作用,可以使用折叠继承体制
2、不必要的委托可以使用将类内联化除掉
3、如果函数的某些参数没被用上,就是使用移除参数
4、如果函数名称带有多余的抽象意味,就使用函数改名
14、令人迷惑的暂时字段
这种情况就某类某实例变量只为某种特定情况而设,可以使用提炼类和引入Null对象
15、过度耦合的消息链
这种情况就是:用户向一个对象请求另一个对象,然后再向后者请求另一个对象,然后再请求另一个对象,这就是消息链
我们可以使用隐藏“委托关系”
代码示例:
class Person{
Department department;
public Department getDepartment(){
return department;
}
}
class Department{
private String Code;
private Person manager;
public Department(Person manager){
this.manager=manager;
}
public Person getManager(){
return manager;
}
}
如果客户需要知道经理,必须先取得Department对象,如:
manager=john.getDepartment().getManager();
如果对客户隐藏Department,可以减少耦合,我们在Person中建立一个简单的委托函数
public Person getManager(){
return department.getManager();
}
现在我们客户获取经理,只需要
manager=john.getManager();
16、中间人
过度使用委托,某个类接口有一半的函数都委托给其他类,这就是过度委托,这时候我们可以使用移除中间人,你会发现这个和上面的正好相反
还有使用以继承取代委托,让委托端成为受委托端的一个子类