重构之前
Movie(影片)
public class Movie {
//儿童片
public static final int CHILDRENS=0;
//普通片
public static final int REGULAR=1;
//新片
public static final int NEW_RELEASE=2;
private String title;
private int priceCode;
public Movie(String title, int priceCode) {
this.title = title;
this.priceCode = priceCode;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public void setPriceCode(int priceCode) {
this.priceCode = priceCode;
}
}
Rental(租赁)
public class Rental {
private Movie movie;
private int dayRented;
public Rental(Movie movie, int dayRented) {
this.movie = movie;
this.dayRented = dayRented;
}
public Movie getMovie() {
return movie;
}
public int getDayRented() {
return dayRented;
}
}
Customer(顾客)
class Customer {
private String _name;
private Vector _rentals = new Vector();
public Customer(String name) {
_name = name;
}
public void addRental(Rental arg) {
_rentals.addElement(arg);
}
public String getName() {
return _name;
}
public String statement(){
double totalAmount = 0;
int frequentRenterPoints = 0;
Enumeration rentals = _rentals.elements();
String result = "Rental Record for " + getName() + "\n";
while (rentals.hasMoreElements()) {
double thisAmount = 0;
Rental each = (Rental) rentals.nextElement();
/**
* 租碟的价格是根据碟的类型进行计算的,
* 一般的碟:
* 2块钱起租赁,超过两天每天1块五
* 新碟:
* 每天三块
* 儿童碟:
* 不足四天都是1.5,超过四天(包括)每天1.5
*/
//determine amounts for each line
switch (each.getMovie().getPriceCode()) {
case Movie.REGULAR:
thisAmount += 2;
if (each.getDaysRented() > 2) {
thisAmount += (each.getDaysRented() - 2) * 1.5;
}
break;
case Movie.NEW_RELEASE:
thisAmount += each.getDaysRented() * 3;
break;
case Movie.CHILDRENS:
thisAmount += 1.5;
if (each.getDaysRented() > 3){
thisAmount += (each.getDaysRented() - 3) * 1.5;
break;
}
}
// add frequent renter points
frequentRenterPoints ++;
// add bonus for a two day new release rental
if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) && each.getDaysRented() > 1) {
frequentRenterPoints ++;
}
// show figures fo this rental
result += "\t" + each.getMovie().getTitle() + "\t" + String.valueOf(thisAmount) + "\n";
totalAmount += thisAmount;
}
//add footer lines
result += "Amount owed is " + String.valueOf(totalAmount) + "\n";
result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points";
return result;
}
}
开始重构
建立可靠的测试环境
重构第一步:增加方法,获取单个影片租赁花了费用
重构第二步:修改变量名称
重构第三步:因为这个方法只使用Rental类,没有使用Customer类,所以把这个方法从Customer类移到Rental类
重构第四步:搬移后,去除参数,同时改变函数名称
重构第五步:测试,看看有没有错误
重构第六步:将thisAmount直接使用each.getCharge()代替
重构第七步:提炼“常客积分计算”,也是把这个方法写到Rental类
重构第八步:把“获取总积分”提炼出来,把这个方法写到Customer类
重构第九步:将租期长度作为参数传入getCharge方法
重构第十步:将影片相关的费用、积分方法Move到Movie类中,将Rental的属性daysRented作为参数。
重构第十一步:运用多态取代与价格相关的条件逻辑。
创建Price价格类,作为抽象类给多种影片类型继承,关联到Movie影片类中
Rental(租赁)
public class Rental {
private Movie movie;
private int dayRented;
public Rental(Movie movie, int dayRented) {
this.movie = movie;
this.dayRented = dayRented;
}
public Movie getMovie() {
return movie;
}
public void setMovie(Movie movie) {
this.movie = movie;
}
public int getDayRented() {
return dayRented;
}
public void setDayRented(int dayRented) {
this.dayRented = dayRented;
}
int getFrequentRenterPoints() {
return movie.getFrequentRenterPoints(getDayRented());
}
}
Customer(顾客)
public class Customer {
private String name;
// 动态数组
Vector _rentals = new Vector();
public Customer(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void addRentals(Rental arg) {
_rentals.addElement(arg);
}
public String statement() {
double totalAmount = 0;
int frequentRenterPoints = 0;
// Enumeration接口定义了从一个数据结构得到连续数据的手段
Enumeration rentals = _rentals.elements();
String result = "Rental Record for" + getName() + "\n";
while (rentals.hasMoreElements()) {
Rental each = (Rental) rentals.nextElement();
result += "\t" + each.getMovie().getTitle() + "\t" + String.valueOf(each.getMovie().getPrice().getCharge(each.getDayRented())) + "\n";
}
result += "Amount owed is " + String.valueOf(getTotalCharge()) + "\n";
result += "You earned " + String.valueOf(getTotalFrequentRenterPoints()) + "frequent renter points";
return result;
}
private int getTotalFrequentRenterPoints(){
int result=0;
Enumeration rentals=_rentals.elements();
while(rentals.hasMoreElements()){
Rental each=(Rental)rentals.nextElement();
result+=each.getMovie().getFrequentRenterPoints(each.getDayRented());
}
return result;
}
private double getTotalCharge(){
double result =0;
Enumeration rentals=_rentals.elements();
while(rentals.hasMoreElements()){
Rental each=(Rental)rentals.nextElement();
result+=each.getMovie().getPrice().getCharge(each.getDayRented());
}
return result;
}
}
Movie(影片)
public class Movie {
// 儿童片
public static final int CHILDRENS = 0;
// 普通片
public static final int REGULAR = 1;
// 新片
public static final int NEW_RELEASE = 2;
private String title;
private int priceCode;
public Movie(String title, int priceCode) {
this.title = title;
setPriceCode(priceCode);
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getPriceCode() {
return priceCode;
}
int getFrequentRenterPoints(int daysRented) {
if ((getPriceCode() == Movie.NEW_RELEASE) && daysRented > 1)
return 2;
else
return 1;
}
private Price price;
public void setPriceCode(int arg) {
switch (arg) {
case REGULAR:
price = new RegularPrice();
break;
case CHILDRENS:
price = new ChildrenPrice();
break;
case NEW_RELEASE:
price = new NewReleasePrice();
break;
default:
throw new IllegalArgumentException("Incorrect Price Code");
}
}
public Price getPrice() {
return price;
}
public void setPrice(Price price) {
this.price = price;
}
}
Price类
运用多态取代与价格相关的条件逻辑。
创建Price价格类,作为抽象类给多种影片类型继承,关联到Movie影片类中,
Price类:
abstract class Price {
abstract int getPriceCode();
abstract double getCharge(int daysRenter);
}
class ChildrenPrice extends Price {
int getPriceCode() {
return Movie.CHILDRENS;
}
double getCharge(int daysRented) {
double result = +1.5;
if (daysRented > 3) {
result += (daysRented - 3) * 1.5;
}
return result;
}
}
class NewReleasePrice extends Price {
int getPriceCode() {
return Movie.NEW_RELEASE;
}
double getCharge(int daysRented) {
return daysRented * 3;
}
}
class RegularPrice extends Price {
int getPriceCode() {
return Movie.REGULAR;
}
double getCharge(int daysRented) {
double result = 2;
if (daysRented > 2) {
result += (daysRented - 2) * 1.5;
}
return result;
}
}
测试
public class Test{
public static void main(String[] args) {
Movie mov1 = new Movie("metal",2);
mov1.setPriceCode(2);
Rental ren = new Rental(mov1,8);
Movie mov2 = new Movie("apple",1);
mov2.setPriceCode(1);
Rental xxx = new Rental(mov2,6);
Customer cus = new Customer("Lee");
cus.addRental(ren);
cus.addRental(xxx);
System.out.println(cus.statement());
}
}