【重构】-重复代码(duplicated Code)

重构一  duplicated Code(重复代码)

场景演义:

议题一

同一个类的两个函数有相同代码片段

重构手法(Extract Method)

把一段代码组织在一起并独立,放进一个独立函数中,并让函数名称解析该函数的用途。

演义讲解

public static void main(String[] args) {
	     A();
	     System.out.println("B"); 
	     System.out.println("C"); 
	}
	
	public static void A(){
	    System.out.println("A");
	}
对上面使用 Extract Method
	public static void main(String[] args) {
	     A();
	     B();
	}
	public static void A(){
	    System.out.println("A");
	}
	
	public static void B(){
		    System.out.println("B"); 
	       System.out.println("C"); 
	}

动机

处理复杂函数,过长函数,细粒度函数容易复用,易注释,易覆写。

重构前

viod printOwing(){
	Enumeration e=orders.elements();
	double outstanding=0.0;
	
	//打印横幅
	System.out.println(...............);
	System.out.println(...............);
	System.out.println(...............);
	
	//计算outstanding值
	while(e.hasMoreElements){
		Order order=(Order)e.nextElement();
		outstanding+=each.getAmout();
	}
	
	//打印细节
	System.out.println?(...............);
	System.out.println?(...............);
}

重构以后

范例一:无局部变量

viod printOwing(){
	Enumeration e=orders.elements();
	double outstanding=0.0;
	//打印横幅
	printOwing()
	//计算outstanding值
	while(e.hasMoreElements){
		Order order=(Order)e.nextElement();
		outstanding+=each.getAmout();
	}
	//打印细节
	System.out.println(...............);
	System.out.println(outstanding);
}


public void printOwing(){
	
	System.out.println(...............);
	System.out.println(...............);
	System.out.println(...............);
	
}

范例二:有局部变量

viod printOwing(){
	Enumeration e=orders.elements();
	double outstanding=0.0;
	//打印横幅
	printOwing()
	//计算outstanding值
	while(e.hasMoreElements){
		Order order=(Order)e.nextElement();
		outstanding+=each.getAmout();
	}
	//有局部变量的extract method的方式
	printdetail(outstanding);
}

public void printdetail(double outstanding){
	//打印细节
	System.out.println(...............);
	System.out.println(outstanding);
}

范例三 对局部变量再赋值

viod printOwing(){
	double outstanding=getOutstanding();
	//打印横幅
	printOwing()
	//有局部变量的extract method的方式
	printdetail(double outstanding);
}

public double getOutstanding(){
	double result=0.0;
	Enumeration e=orders.elements();
	//计算outstanding值
	while(e.hasMoreElements){
		Order order=(Order)e.nextElement();
		result+=each.getAmout();
	}
	return result;
}


public void printOwing(){
	
	System.out.println(...............);
	System.out.println(...............);
	System.out.println(...............);
	
}


public void printOwing(){
	
	System.out.println(...............);
	System.out.println(...............);
	System.out.println(...............);
	
}

public void printdetail(double outstanding){
	//打印细节
	System.out.println(...............);
	System.out.println(outstanding);
}

议题二

两个互为兄弟的子类有相同代码片段

重构手法

extract method(提取重复代码)

Pull UpMethod(推入超类):有些函数在各个子类中产生完全相同的效果,将该函数移至超类中。


动机

避免修改一个而没有修改另一个,有大量冗余的工作要做

如上图所示 我们可以看到两个子类中都有createBill()和chargeFor(Date start,Date end)

这两个方法,遗憾的是只有createBill()方法是相同的,然而chargeFor方法确实不同的,所以我们只能使用pull up method 把createBill(); 提取到超类中,在超类中申明chargeFor方法为抽象方法。

class Customer{
	public abstract double chargeFor(Date start,Date end);

}

如上类图所示 createBill已经通过pull up method提升到超类中了,chargeFor也在超类中被申明为了一个抽象类。

FormTemplate Method(模板方法)

一些子类,其中相应的某些函数以相同顺序执行类似操作,但各个操作细节上有所不同。将这些函数都放进独立的函数中,并保持他们都有相同的签名,于是原函数也变得相同了,然后将原函数移至超类。


如上所示。原本有两个子类都有同名函数。可是有些操作却不一样,把这些不同的操作以相同的函数签名用extract method抽取成独立的单元,把原函数pull up mehtod上升到父类中,再把这些不同的函数的公共方法签名作为抽象方法,放进超类中。

动机:两个子类之中有类似的函数,就可以提升至超类中,两个函数执行以大致相近的操作,又不完全相同,可以将完全相同的的顺序移至超类中,并借助多态来保持差异,这样的函数称为模板方法。

 

重构前范例
public Class Statement{
	
	public String  stateString(){
		String result=null;
		result=result+"你好";
		result=result+"是的"
		return result;
	}
	
}

public String  stateString(){
		String result=null;
		result=result+"<html><head></hea><body>你好";
		result=result+"是的</body></html>"
		return result;
}
	
}

如上代码段所示,是两种不同方式的问好方法,一个是html的方式,一个是普通字符串的方式,但是它们都实现同样的效果。此时我们应该把这两个方法作为两种策略,封装成两个类


第一步 并把两个实现相同功能的方法封装,重新进行方法签名

public class Statement{
	
	
}
public class Htmlstatement extends Statement{
	
	public String  value(){
		String result=null;
		result=result+"<h1>欢迎你</h1>";
		result=result+"<html><head></hea><body>你好";
		result=result+"我是小梅</body></html>"
		return result;
	}
}



public class Textstatement extends Statement{
	
	public String  value(){
		String result=null;
		result=result+"欢迎你";
		result=result+"你好";
		result=result+"我是小龙"
		return result;
	}
	
}

第二步:提取相同序列中的不同部门,代之以相同的方法签名

public class Statement{
	
	
}
public class Htmlstatement extends Statement{
	
	public String  value(String customer){
		String result=null;
		result=result+headString(customer);
		result=result+eachRentalString(customer);
		result=result+footerString(customer);
		return result;
	}
	
	
	public String headString(String customer){
		return "<h1>欢迎你</h1>";
	}
	
	public String eachRentalString(String rental){
		return "<html><head></hea><body>你好";
	}
	
	public footerString(String customer){
		return "我是小梅</body></html>";
	}
}



public class Textstatement extends Statement{
	
	public String  value(String customer){
		String result=null;
		result=result+headString(customer);
		result=result+eachRentalString(customer);
		result=result+footerString(customer);
		return result;
	}
	
	public String headString(String customer){
		return "欢迎你"+ customer;
	}
	
	public String eachRentalString(String rental){
		return "你好"+ Rental;
	}
	
	public footerString(String customer){
		return "我是小龙"+ customer;
		
	}
}

第三步 把相同的序列方法用pull up method 提到超类中,把相同的方法签名在超类中利用抽象方法进行申明。

public class Statement{
	public String  value(String customer){
		String result=null;
		result=result+headString(customer);
		result=result+eachRentalString(customer);
		result=result+footerString(customer);
		return result;
	}
	public abstract String headString(String customer);
	public abstract String eachRentalString(String rental);
	public abstract String footerString(String customer);
	
}

子类不做改变:

重构完毕后的类图。

SubstituteAlgorithm(替换算法)

将某个算法替换为另一个更清晰的算法。

议题三

多个毫不相干的类中有相同代码片段

重构手法

ExtractClass 提炼类:某个类做了应该由两个类做的事情,建立一个新类,将相关字段和函数从旧类搬移到新类。


一个类应该是一个清楚的抽象,处理一些明确的责任。

重构前:

public class Person{
	private String name;
	private String areaCode;
	private String areaphomenum;
	
	public void setName(String name){
		this.name=name;
	}
	
	public String getName(){
		retunr this.name;
	}
	
	public String getTeleAcreCode(){
		return this.areaCode;
	}
	
	public String getAreaPhone(){
		return this.areaphomenum;
	}
	
}
我们看到跟电话相关的类似乎有点冗余,所以我们应该把它抽取出去

public class TelePhoneNumber{
	private String number;
	private String code;
	
	public String getNumber(){
	   return number;
	}
	
	public String getCode(){
		return code;
	}
	
}

接下来我们把 TelephoneNumber这个类组合进去












  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值