1. 程式人生 > >重構,第一個案例,重構前的程式碼

重構,第一個案例,重構前的程式碼

《重構:改善既有程式碼的設計》第一章 重構,第一個案例

 此程式碼用於練習重構手法,侵刪!

影片類:

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();

運用多型取代與價格相關的條件邏輯;