定义:在不改变代码外在行为的前提下,对代码做出修改,以改进程序内部结构。
重构第一例。
Movie:
package refactoring; public class Movie { public static final int CHILDRENS = 2; public static final int REGULAR = 0; public static final int NEW_RELEASE = 1; private String title; // private int priceCode; private Price price; public Movie(String title, int priceCode) { this.title = title; // this.priceCode = priceCode; setPriceCode(priceCode); // self encapsulate field } public int getPriceCode() { // return priceCode; return price.getPriceCode(); } public void setPriceCode(int priceCode) { // this.priceCode = 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"); } } public double getCharge(int daysRented) { return price.getCharge(daysRented); } public String getTitle() { return title; } public int getFrequentRenterPoints(int daysRented) { return price.getFrequentRenterPoints(daysRented); } }
2.Customer:
package refactoring; import java.util.Enumeration; import java.util.Vector; public class Customer { private String name; private Vector<Rental> rentals = new Vector<Rental>(); public Customer(String name) { this.name = name; } public void addRental(Rental rental) { this.rentals.add(rental); } public String getName() { return this.name; } public String statement() { Enumeration<Rental> rens = this.rentals.elements(); String result = "Rental Record for " + getName() + "\n"; while(rens.hasMoreElements()) { Rental ren = rens.nextElement(); // replace temp with query // double thisAmount = ren.getCharge(); // 就函数的引用点ren.getCharge(); // 在每次循环的时候 frequentRenterPoints已经有一个初始值 所以此处直接进行一个 附添赋值操作 result += "\t" + ren.getMovie().getPriceCode() + "\t" + ren.getCharge() + "\t"; } // 共金额 result += "Amount owed is " + getTotalCharge() + "\n"; // 总积分 result += "You earned " + getTotalFrequentRenterPoints() + " frequent renter points"; return result; } // query method (replace temp with query) private double getTotalCharge() { double result = 0; Enumeration<Rental> rens = rentals.elements(); while(rens.hasMoreElements()) { Rental rental = (Rental) rens.nextElement(); result += rental.getCharge(); } return result; } private int getTotalFrequentRenterPoints() { int result = 0; Enumeration<Rental> rens = rentals.elements(); while(rens.hasMoreElements()) { Rental rental = (Rental) rens.nextElement(); result += rental.getFrequentRenterPoints(); } return result; } }
3.Rental:
package refactoring; /** * 租赁实体 * @author zhy * */ public class Rental { private Movie movie; private int daysRented; public Rental(Movie movie, int daysRented) { this.movie = movie; this.daysRented = daysRented; } public Movie getMovie() { return movie; } public int getDaysRented() { return daysRented; } // 付的总金额 public double getCharge() { return movie.getCharge(daysRented); } // 客户的积分总和 public int getFrequentRenterPoints() { return movie.getFrequentRenterPoints(daysRented); } }
4.Price:
package refactoring; public abstract class Price { abstract int getPriceCode(); //replace Conditional with Polymorphism abstract double getCharge(int daysRented); public int getFrequentRenterPoints(int daysRented) { return 1; } }
5.ChildrensPrice
package refactoring; public class ChildrensPrice extends Price { @Override int getPriceCode() { return Movie.CHILDRENS; } public double getCharge(int daysRented) { double result = 1.5; if(daysRented > 3) { result = (daysRented - 3) * 1.5; } return result; } }
6.NewReleasePrice
package refactoring; public class NewReleasePrice extends Price { @Override int getPriceCode() { return Movie.NEW_RELEASE; } public double getCharge(int daysRented) { return daysRented * 3; } public int getFrequentRenterPoints(int daysRented) { return daysRented > 1 ? 2 : 1; } }
7.RegularPrice:
package refactoring; public class RegularPrice extends Price { @Override int getPriceCode() { return Movie.REGULAR; } public double getCharge(int daysRented) { double result = 2; if(daysRented > 2) { result += (daysRented - 2) * 1.5; } return result; } }