第一章最前面的书中前面的话说得很有道理,一本授之以渔的书,开场就来历史、原理性的东西,很难勾起继续阅读的欲望,写书是这样,开会做分享亦然,所以作者精挑细选了一个代码规模不是很大并且能告诉我们很多重构的道理。
案例说明
这是一个非常简单的案例,展示了一个影片出租店用的程序,计算每一位顾客的消费金额并打印详单的模块,同时还需要计算每一位客人的积分。给出一个 UML 图,是最初版本。
抽象了三个实体:影片(片名、片类型)、租赁(影片、租赁天数)、顾客(姓名、租赁清单),代码详见下面的三个类以及 MainClass。
public class Customer { private String name; private Vector<Rental> rentals = new Vector<Rental>(); public Customer(String name) { this.name = name; } public String getName() { return name; } public Vector<Rental> getRentals() { return rentals; } public void addRentals(Rental rental) { this.rentals.add(rental); } public String statement() { double totalAmount = 0; int frequentRenterPointers = 0; Enumeration<Rental> rentalEnumeration = rentals.elements(); String result = "Rental Records for " + getName() + "\n"; while (rentalEnumeration.hasMoreElements()) { double thisAmount = 0; Rental each = rentalEnumeration.nextElement(); // determine amounts for each line switch (each.getMovie().getPriceCode()) { case Movie.REGULAR: thisAmount += 2; if (each.getDayRented() > 2) { thisAmount += (each.getDayRented() - 2) * 1.5; } break; case Movie.NEW_RELEASE: thisAmount += each.getDayRented() * 3; break; case Movie.CHILDREN: thisAmount += 1.5; if (each.getDayRented() > 3) { thisAmount += (each.getDayRented() - 3) * 1.5; } break; } // add frequent renter points frequentRenterPointers++; // add bonus for two day new release rental if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) && each.getDayRented() > 1) { frequentRenterPointers++; } //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 " + frequentRenterPointers + " frequent renter points"; return result; } } public class Movie { public static final int REGULAR = 0; public static final int NEW_RELEASE = 1; public static final int CHILDREN = 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 int getPriceCode() { return priceCode; } public void setPriceCode(int priceCode) { this.priceCode = priceCode; } } 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; } } public class MainClass { public static void main(String[] args) { // 三部影片 Movie movie1 = new Movie("复仇者联盟", Movie.NEW_RELEASE); Movie movie2 = new Movie("超能陆战队", Movie.CHILDREN); Movie movie3 = new Movie("澳门风云", Movie.REGULAR); //两名顾客 Customer customer1 = new Customer("Jack"); Customer customer2 = new Customer("Stary"); //顾客租约 Rental rental1 = new Rental(movie1, 5); Rental rental2 = new Rental(movie2, 3); Rental rental3 = new Rental(movie3, 3); customer1.addRentals(rental1); customer1.addRentals(rental2); customer2.addRentals(rental2); customer2.addRentals(rental3); String statement1 = customer1.statement(); String statement2 = customer2.statement(); System.out.println(statement1); System.out.println("-----------------------"); System.out.println(statement2); } }
重构前提是不改变源程序的输出结果,原始的运行结果如下: