有一批重构手法专门用来处理类的概括关系,即继承关系。其中主要是将函数上下移动于继承体系之中。
1、PullUpField(字段上移)
两个子类拥有相同的字段。将该字段移至超类。
2、PullUpMethod(函数上移)
有些函数,在各个类中产生完全相同的结果。将该函数移至超类。
3、PullUpConstructorBody(构造函数本体上移)
你在各个子类中拥有一些构造函数,它们本体几乎完全一致。在超类中新建一个构造函数,并在子类构造函数中调用它。
代码1:
classManagerextendsEmployee...
publicManager(Stringname,Stringid,intgrade){
_name=name;
_id=id;
_grade=grade;
}
代码2:
publicManager(Stringname,Stringid,intgrade){
super(name,id);
_grade=grade;
}
4、PushDownMethod(函数下移)
超类中的某个函数只与部分(而非全部)子类有关。将这个函数移到相关的那些子类去。
5、PushDownField(字段下移)
超类中的某个字段只被部分(而非全部)子类用到。将这个字段移到需要它的那些子类去。
6、ExtractSubclass(提炼子类)
类中的某些特性只被某些(而非全部)实例用到。新建一个子类,将上面所说的那一部分特性移到子类中。
7、ExtractSuperclass(提炼超类)
两个类有相似特性。为这两个类建立一个超类,将相同特性移至超类。
8、ExtractInterface(提炼接口)
若干客户使用类接口中的同一子集,或者两个类的接口有部分相同。将相同的子集提炼到一个独立接口中。
9、CollapseHierarchy(折叠继承体系)
10、FormTemplateMethod(塑造模板函数)
动机:你有一些子类,其中相应的某些函数以相同顺序执行类似的操作,但各个操作的细节上有所不同。
做法:将这些操作分别放进独立函数中,并保持它们都有相同的签名,于是原函数也就变得相同。然后将原函数上移至超类。
代码1:
class Customer {
public String statement(){
return new TextStatement().value(this);
}
public String htmlStatement(){
return new HtmlStatement().value(this);
}
}
class TextStatement{
public String value(Customer aCustomer){
Enumeration<e> rentals = aCustomer.getRentals();
String result = "Rental Record for " + aCustomer.getName() + "\n";
while(rentals.hasMoreElements()){
Rental each = (Rental) rentals.nextElement();
//show figures for this rental
result += "\t" + each.getMovie().getTitle() + "\t"
+ String.valueOf(each.getCharge()) + "\n";
}
//add footer lines
result += "Amount owed is "
+ String.valueOf(aCustomer.getTotalCharge()) + "\n";
result += "You earned "
+ String.valueOf(aCustomer.getTotalFrequentRenterPoints())
+ " frequent renter points";
return result;
}
}
class HtmlStatement {
public String value(Customer aCustomer){
Enumeration<e> rentals = aCustomer.getRentals();
String result = "<H1>Rental Record for <EM>" + aCustomer.getName()
+ "</EM></H1><P>\n";
while(rentals.hasMoreElements()){
Rental each = (Rental) rentals.nextElement();
//show figures for this rental
result += each.getMovie().getTitle() + ":"
+ String.valueOf(each.getCharge()) + "<BR>\n";
}
//add footer lines
result += "<P>You owed <EM>"
+ String.valueOf(aCustomer.getTotalCharge()) + "</EM><P>\n";
result += "On this rental you earned <EM> "
+ String.valueOf(aCustomer.getTotalFrequentRenterPoints())
+ "</EM> frequent renter points<P>";
return result;
}
}
代码2:将上面两个类中不同的地方抽出来,分别放进独立函数中。
class TextStatement{
String headerString(Customer aCustomer){
return "Rental Record for " + aCustomer.getName() + "\n";
}
String eachRentalString(Rental aRental){
return "\t" + aRental.getMovie().getTitle() + "\t"
+ String.valueOf(aRental.getCharge()) + "\n";
}
String footerString(Customer aCustomer){
return "Amount owed is "
+ String.valueOf(aCustomer.getTotalCharge()) + "\n"
+"You earned "
+ String.valueOf(aCustomer.getTotalFrequentRenterPoints())
+ " frequent renter points";
}
public String value(Customer aCustomer){
Enumeration<e> rentals = aCustomer.getRentals();
String result = headerString(aCustomer);
while(rentals.hasMoreElements()){
Rental each = (Rental) rentals.nextElement();
//show figures for this rental
result += eachRentalString(each);
}
//add footer lines
result += footerString(aCustomer);
return result;
}
}
class HtmlStatement {
String headerString(Customer aCustomer){
return "<H1>Rental Record for <EM>" + aCustomer.getName()
+ "</EM></H1><P>\n";
}
String eachRentalString(Rental aRental){
return aRental.getMovie().getTitle() + ":"
+ String.valueOf(aRental.getCharge()) + "<BR>\n";
}
String footerString(Customer aCustomer){
return "<P>You owed <EM>"
+ String.valueOf(aCustomer.getTotalCharge()) + "</EM><P>\n"
+ "On this rental you earned <EM> "
+ String.valueOf(aCustomer.getTotalFrequentRenterPoints())
+ "</EM> frequent renter points<P>";
}
public String value(Customer aCustomer){
Enumeration<e> rentals = aCustomer.getRentals();
String result = headerString(aCustomer);
while(rentals.hasMoreElements()){
Rental each = (Rental) rentals.nextElement();
//show figures for this rental
result += eachRentalString(each);
}
//add footer lines
result += footerString(aCustomer);
return result;
}
}
代码3:经过第二步处理,我们将相同的函数提炼到超类中。函数内容不同提炼为抽象类。
abstract class Statement{
abstract String headerString(Customer aCustomer);
abstract String eachRentalString(Rental aRental);
abstract String footerString(Customer aCustomer);
public String value(Customer aCustomer){
Enumeration<e> rentals = aCustomer.getRentals();
String result = headerString(aCustomer);
while(rentals.hasMoreElements()){
Rental each = (Rental) rentals.nextElement();
//show figures for this rental
result += eachRentalString(each);
}
//add footer lines
result += footerString(aCustomer);
return result;
}
}
第四步:TextStatement、HtmlStatement继承Statement,并实现抽象函数。
11、ReplaceInheritancewithDelegation(以委托取代继承)
动机:某个子类只使用接口中的一部分,或是根本不需要继承而来的数据。
代码1:只要看看MyStack的用户,我就会发现,用户只要它做4件事:push()、pop()、size()和isEmpty()。后两个函数就是从Vector继承来的。
classMyStackextendsVector{
publicvoidpush(Objectelement){
insertElementAt(element,0);
}
publicObjectpop(){
Objectresult=firstElement();
removeElementAt(0);
returnresult;
}
}
代码2:跟封装模式有点类似,只不过只封装了需要用到的函数。
classMyStack{
privateVector_vector=newVector();
publicvoidpush(Objectelement){
_vector.insertElementAt(element,0);
}
publicObjectpop(){
Objectresult=_vector.firstElement();
_vector.removeElementAt(0);
returnresult;
}
publicintsize(){
return_vector.size();
}
publicbooleanisEmpty(){
return_vector.isEmpty();
}
}
12、ReplaceDelegationwithInheritance(以继承取代委托)
动机:需要用到受委托类的所有函数。
分享到:
相关推荐
第11章 处理概括关系 11.1 Pull Up Field(值域上移) 11.2 Pull Up Method(函数上移) 11.3 Pull Up Co tructor Body(构造函数本体上移) 11.4 Push Down Method(函数下移) 11.5 Push Down Field(值域下移) ...
第11章 处理概括关系 319 11.1 Pull Up Field(字段上移) 320 11.2 Pull Up Method(函数上移) 322 11.3 Pull Up Constructor Body(构造函数本体上移) 325 11.4 Push Down Method(函数下移) 328 ...
第11章 处理概括关系319 11.1 PullUpField(字段上移)320 11.2 PullUpMethod(函数上移)322 11.3 PullUpConstructorBody(构造函数本体上移)325 11.4 PushDownMethod(函数下移)328 11.5 PushDownField(字段...
2.6 重构与设计······ ·· · · ······· ·· ···· · ··· ·· · · ··· ·· ·· ····· · · · ·· ·· ·· ··· ·· ·· · ·· ·· ···· · ···· · · ·...
第11章 处理概括关系 11.1 Pull Up Field(值域上移) 11.2 Pull Up Method(函数上移) 11.3 Pull Up Co tructor Body(构造函数本体上移) 11.4 Push Down Method(函数下移) 11.5 Push Down Field(值域下移) ...
第11章 处理概括关系319 11.1 PullUpField(字段上移)320 11.2 PullUpMethod(函数上移)322 11.3 PullUpConstructorBody(构造函数本体上移)325 11.4 PushDownMethod(函数下移)328 11.5 PushDownField(字段...
按照传统,书籍应该以一个简介开头口尽管我也同意这个原则,但是我发现以概括性的讨论或定义来介绍重构,实在不是件容易的事。所以我决定拿一个实例做为开路先锋。 第1章展示一个小程序,其中有些常见的设汁缺陷,...
第11章 处理概括关系319 11.1 PullUpField(字段上移)320 11.2 PullUpMethod(函数上移)322 11.3 PullUpConstructorBody(构造函数本体上移)325 11.4 PushDownMethod(函数下移)328 11.5 PushDownField(字段...
作者:Martin Fowler,Kent Beck,John Brant ,William Opdyke ,Don Roberts 翻译:侯捷、熊节 ...章节十一 处理概括关系 章节十二 大型重构 章节十三 重构,复用与现实 章节十四 重构工具 章节十五 集成
第11章 处理概括关系319 11.1 PullUpField(字段上移)320 11.2 PullUpMethod(函数上移)322 11.3 PullUpConstructorBody(构造函数本体上移)325 11.4 PushDownMethod(函数下移)328 11.5 PushDownField(字段...
重构,一言以蔽之,就是在不改变外部行为的前提下,有条不紊地改善代码。多年前,正是本书原版的出版,使重构终于从编程高手们的小圈子走出,成为众多普通程序员日常开发工作中不可或缺的一部分。本书也因此成为与...
第 11 章:处理概括关系(Dealing with Generalization) 第 12 章:大型重构(Big Refactorings, by Kent Beck and Martin Fowler) 第 13 章:重构、复用与现实 第 14 章:重构工具(Refactoring Tools, ...
1、重构起源、概述 ...6、6处理概括关系(DealingwithGeneralization) 7、大型重构(BigRefactorings) 8、重构、复用、与现实(Refactoring,Reuse,andReality) 9、重构工具(RefactoringTools)
重构,一言以蔽之,就是在不改变外部行为的前提下,有条不紊地改善代码。多年前,正是本书原版的出版,使重构终于从编程高手们的小圈子走出,成为众多普通程序员日常开发工作中不可或缺的一部分。本书也因此成为与...