上一篇文章:java 代码重构-第一章(终于…我们来到继承(Inheritance))
下一篇文章:java 代码重构-第一章(使用策略模式,把恶心的switch代码去掉...) 二
现在我加入新class,并在Price 对象中提供「与型别相依的行为」。为了实现这一点,我在Price 内加入一个抽象函数(abstract method ),并在其所有subclasses 中加上对应的具体函数(concrete method):
首先我创建一个类
Price
package com.mkfree.refactoring.shap1; /** * 金额 * * @author hk * * 2013-1-4 下午7:30:53 */ public abstract class Price { abstract int getPriceCode(); // 取得价格代号 }
下面用了java设计模式中的策略模式,如果有很大疑问可以参考:java设计模式 策略模式(strategy pattern)
RegularPrice
package com.mkfree.refactoring.shap1; /** * 普通电影 * * @author hk * * 2013-1-4 下午7:35:26 */ class RegularPrice extends Price { int getPriceCode() { return Movie.REGULAR; } }
ChildrensPrice
package com.mkfree.refactoring.shap1; /** * 儿童电影 * * @author hk * * 2013-1-4 下午7:35:08 */ public class ChildrensPrice extends Price { @Override int getPriceCode() { return Movie.CHILDRENS; } }
NewReleasePrice
package com.mkfree.refactoring.shap1; /** * 新发布电影 * * @author hk * * 2013-1-4 下午7:34:55 */ class NewReleasePrice extends Price { int getPriceCode() { return Movie.NEW_RELEASE; } }
现在我可以编译这些新classes了。
现在,我需要修改Movie class 内的「价格代号」访问函数(get/set函数,如下),让它们使用新class。
下面是重构前的样子:
Movie
private int priceCode; public String getTitle() { return title; } public int getPriceCode() { return priceCode; }
这意味我必须在Movie class 内保存一个Price 对象,而不再是保存一个priceCode 变量。此外我还需要修改访问函数(译注:即get/set函数):
重构如下代码:
private int priceCode; public int getPriceCode() { return price.getPriceCode(); } /** * priceCode就new那种price出来(策略模式) * * @param priceCode */ public void setPriceCode(int priceCode) { switch (priceCode) { case REGULAR: price = new RegularPrice(); break; case CHILDRENS: price = new ChildrensPrice(); break; case NEW_RELEASE: price = new NewReleasePrice(); break; default: throw new IllegalArgumentException("Incorrect Price Code"); } }
现在我可以重新编译并测试,那些比较复杂的函数根本不知道世界巳经变了个样儿。
结果:
Rental Record for oyhk 少林足球 6.0 大话西游 1.5 Amount owed is 7.5 You earned 3 frequent renter points ------------------------------------------------ <H1>Rentals for <EM>oyhk</EM></ H1><P> 少林足球: 6.0<BR> 大话西游: 1.5<BR> <P>You owe <EM>7.5</EM><P> On this rental you earned <EM>3</EM> frequent renter points<P>
证明重构成功啦...结果还是一样,没变...
好了,下面到移动方法了,要对getCharge() 实施Move Method。
Movie 重构前代码:
class Movie... double getCharge(int daysRented) { double result = 0; switch (getPriceCode()) { case Movie.REGULAR: result += 2; if (daysRented > 2) result += (daysRented - 2) * 1.5; break; case Movie.NEW_RELEASE: result += daysRented * 3; break; case Movie.CHILDRENS: result += 1.5; if (daysRented > 3) result += (daysRented - 3) * 1.5; break; } return result; }
搬移动作很简单。下面是重构后的代码。
Priice 添加一个方法
package com.mkfree.refactoring.shap1; /** * 金额 * * @author hk * * 2013-1-4 下午7:30:53 */ public abstract class Price { abstract int getPriceCode(); // 取得价格代号 /** * 获取收费 * * @param daysRented * @return */ double getCharge(int daysRented) { double result = 0; switch (getPriceCode()) { case Movie.REGULAR: result += 2; if (daysRented > 2) result += (daysRented - 2) * 1.5; break; case Movie.NEW_RELEASE: result += daysRented * 3; break; case Movie.CHILDRENS: result += 1.5; if (daysRented > 3) result += (daysRented - 3) * 1.5; break; } return result; } }
搬移之后,我就可以开始运用Replace Conditional with Polymorphism了。下面是重构前的代码。
Movie
Movie{..... /** * 获取收费 * * @param daysRented * @return */ double getCharge(int daysRented) { return price.getCharge(daysRented); } }
搬移完成后,再运行代码,测试下是否正常,结果如下,正常...
Rental Record for oyhk 少林足球 6.0 大话西游 1.5 Amount owed is 7.5 You earned 3 frequent renter points ------------------------------------------------ <H1>Rentals for <EM>oyhk</EM></ H1><P> 少林足球: 6.0<BR> 大话西游: 1.5<BR> <P>You owe <EM>7.5</EM><P> On this rental you earned <EM>3</EM> frequent renter points<P>