《重构:改善既有代码的设计》第一章 重构,第一个案例
此代码用于练习重构手法,侵删!
影片类:
public class Movie {
public final static int REGULAR = 0;
public final static int NEW_RELEASE = 1;
public final static int CHILDRENS = 2;
private String title;
private int priceCode;
public Movie(String title, int priceCode) {
super();
this.title = title;
this.priceCode = priceCode;
}
public int getPriceCode() {
return priceCode;
}
public void setPriceCode(int priceCode) {
this.priceCode = priceCode;
}
public String getTitle() {
return title;
}
}
租赁类:
public class Rental {
private Movie movie;
private int daysRented;
public Rental(Movie movie, int daysRented) {
super();
this.movie = movie;
this.daysRented = daysRented;
}
public Movie getMovie() {
return movie;
}
public int getDaysRented() {
return daysRented;
}
}
顾客类:
import java.util.Enumeration;
import java.util.Vector;
public class Customer {
private String name;
private Vector<Rental> rentals = new Vector<>();
public Customer(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void addRental(Rental rental) {
rentals.add(rental);
}
public String statement() {// 生成详单
double totalAmount = 0;
int frequentRenterPoints = 0;
Enumeration<Rental> rentals = this.rentals.elements();
String result = "Rental record for " + getName() + "\n";
while (rentals.hasMoreElements()) {
double thisAmount = 0;
Rental each = rentals.nextElement();
// 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 for this rental
result += "\t"+each.getMovie().getTitle()+"\t"+thisAmount+"\n";
totalAmount += thisAmount;
}
// add footer lines
result += "Amount owed is " + totalAmount + "\n";
result += "You earned " + frequentRenterPoints
+ "frequent renter points";
return result;
}
}
首先,建立一组可靠的测试环境:
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class CustomerTest {
private Customer customer;
@BeforeEach
void init() {
customer = new Customer("小明");
customer.addRental(new Rental(new Movie("喜剧之王", Movie.REGULAR), 3));
customer.addRental(new Rental(new Movie("国产零零柒", Movie.REGULAR), 5));
customer.addRental(new Rental(new Movie("西虹市首富", Movie.NEW_RELEASE), 1));
customer.addRental(new Rental(new Movie("猫和老鼠", Movie.CHILDRENS), 6));
}
@Test
void testStatement() {
String statement = customer.statement();
String expected = "Rental record for 小明\n" +
"\t喜剧之王\t3.5\n" +
"\t国产零零柒\t6.5\n" +
"\t西虹市首富\t3.0\n" +
"\t猫和老鼠\t6.0\n" +
"Amount owed is 19.0\n" +
"You earned 4frequent renter points";
assertEquals(expected , statement);
}
@Test
void testHtmlStatement() {
String htmlStatement = customer.htmlStatement();
String expected = "<H1>Rentals for <EM>小明</EM></H1><P>\n" +
"喜剧之王: 3.5<BR/>\n" +
"国产零零柒: 6.5<BR/>\n" +
"西虹市首富: 3.0<BR/>\n" +
"猫和老鼠: 6.0<BR/>\n" +
"<P>You owe <EM>19.0</EM></P>\n" +
"On this rental you earned <EM>4</EM> frequent renter points</P>";
assertEquals(expected , htmlStatement);
}
}
重构操作(略):
分解并重组 statement();
运用多态取代与价格相关的条件逻辑;