测试驱动示例,应用重构优化设计
下面通过一个简单的测试驱动示例,并经过重构完成设计的更改。详细的例子见重构。
影片出租店的程序,计算每一位顾客的消费金额并打印报表。操作者告诉程序:顾客租用了哪些影片,租期多长,程序根据租赁时间和影片类型(普通片,儿童片和新片)。除了计算费用,还要为常客计算点数,点数的计算会由于租片种类是否为新片而有所不同。
根据上述描述,我们画出简单的类图
其中影片和租借都是简单的纯数据类。
package chapter01;
public class Movie {
public static final int CHILDRENS=2;//
影片类型
public static final int REGULAR=1;
public static final int NEW_RELEASE=0;
private String title;//
名称
private int priceCode;//
价格代码
public Movie(String title, int priceCode) {
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 dayRented;
public Rental(Movie movie, int dayRented) {
this.movie = movie;
this.dayRented = dayRented;
}
public int getDayRented() {
return dayRented;
}
public Movie getMovie() {
return movie;
}
}
public class Customer {
private String name;
private Vector rentals=new Vector();
public Customer(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Vector getRentals() {
return rentals;
}
@SuppressWarnings("unchecked")
public void addRental(Rental rental){
rentals.add(rental);
}
public String statement(){//
计算费用
double totalAmount=0;//
总和
int frequentCount=0;//
常客积点
Enumeration rental=rentals.elements();
String result="rental record for "+getName()+"\n";
while (rental.hasMoreElements()) {
Rental each = (Rental) rental.nextElement();//
取得一批租借记录
double thisAmount=0;
//
根据类型,计算价格
switch (each.getMovie().getPriceCode()) {
case Movie.REGULAR:
thisAmount+=2;
if(each.getDayRented()>2)
thisAmount+=(each.getDayRented()-2)*1.5;
break;
case Movie.CHILDRENS:
thisAmount+=1.5;
if(each.getDayRented()>3)
thisAmount+=(each.getDayRented()-3)*1.5;
break;
case Movie.NEW_RELEASE:
thisAmount+=(each.getDayRented())*3;
break;
}
//
添加常客积点
frequentCount++;
if (each.getMovie().getPriceCode()==Movie.NEW_RELEASE&&each.getDayRented()>1)
frequentCount++;
//
显示此笔数据
result+=
"\t"+each.getMovie().getTitle()+
"\t"+String.valueOf(frequentCount)+"\n";
totalAmount+=thisAmount;
}
//
打印结尾
result+="amount owned "+String.valueOf(totalAmount)+"\n";
result+="you earned "+String.valueOf(frequentCount)+"frequentCount\n";
return result;
}
}
下面是对应的测试用例
public class testCustomerStatement extends TestCase {
Movie childrenMovie=new Movie("HARRY POTTY",Movie.CHILDRENS);
Movie regularMovie=new Movie("Titanic",Movie.REGULAR);
Movie newMovie=new Movie("Ice Age 2",Movie.NEW_RELEASE);
Rental childRental=new Rental(childrenMovie,3);
Rental newRental=new Rental(newMovie,5);
Rental regRental=new Rental(regularMovie,5);
Customer tom=new Customer("Tom");
protected void setUp() throws Exception {
super.setUp();
tom.addRental(childRental);
tom.addRental(newRental);
tom.addRental(regRental);
}
public void testCaustomerName(){
assertEquals("Tom",tom.getName());
}
public void testIteratorSize(){
assertEquals(3,tom.getRentals().size());
}
public void testIteratorName(){
Enumeration rentals=tom.getRentals().elements();
while (rentals.hasMoreElements()) {
Rental each = (Rental) rentals.nextElement();
switch(each.getMovie().getPriceCode()){
case Movie.CHILDRENS:
System.out.println("childrens");
assertEquals("HARRY POTTY",each.getMovie().getTitle());
assertEquals(3,each.getDayRented());
break;
case Movie.NEW_RELEASE:
System.out.println("new");
assertEquals("Ice Age 2",each.getMovie().getTitle());
assertEquals(5,each.getDayRented());
break;
case Movie.REGULAR:
System.out.println("regular");
assertEquals("Titanic",each.getMovie().getTitle());
assertEquals(5,each.getDayRented());
break;
}
}
}
public void testOutput(){
System.out.println(tom.statement());
}
}