重构,第一个案例,重构前的代码

《重构:改善既有代码的设计》第一章 重构,第一个案例

 此代码用于练习重构手法,侵删!

影片类:

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

运用多态取代与价格相关的条件逻辑;

 

/* * 原始需求背景: * 网宿CDN要按月收取客户的服务费用,根据流量的大小、 * 服务的类型等,收取不同的费用,收费规则如下: * web应用:1000元/M * 流媒体应用:1000元/M*0.7 * 下载应用:1000元/M*0.5 * 月末打印报表时,要罗列每个用户每个频道的费用、客户总费用, * 还要打印该客户的重要性指数,重要性指数=网页流/100+下载流量/600; * * 需求变更场景: * 系统已经开发出来了,接下来,运维部门现在希望对系统做一点修改, * 首先,他们希望能够输出xml,这样可以被其它系统读取和处理,但是, * 这段代码根本不可能在输出xml的代码中复用report()的任何行为,唯一 * 可以做的就是重写一个xmlReport(),大量重复report()中的行为,当然, * 现在这个修改还不费劲,拷贝一份report()直接修改就是了。 * 不久,成本中心又要求修改计费规则,于是我们必须同时修改xmlReport() * 和report(),并确保其一致性,当后续还要修改的时候,复制-黏贴的问题就 * 浮现出来了,这造成了潜在的威胁。 * 再后来,客服部门希望修改服务类型和用户重要性指数的计算规则, * 但还没决定怎么改,他们设想了几种方案,这些方案会影响用户的计费规则, * 程序必须再次同时修改xmlReport()和report(),随着各种规则变得越来越复杂, * 适当的修改点越 来越难找,不犯错误的机会越来越少。 * 现在,我们运用所学的OO原则和方法开始进行改写吧。 */
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值