wiki:codekata/harrypotter3

2013年9月6日代码道场活动纪实

代码道场的参与者:秦鸿源,陈阳,王安宁,丁健勇,李炳岳,黄志强,李剑文,张艺辉,江毅超, 李峰

地点:4G会议室

回顾一下,上几期,我们做了购书活动的扩展

	单集购买5本,优惠7元。
	支持买6送1活动。
	支持购买100元送10活动。

经过讨论,我们打算将扩展进行到底,我们再添加一种扩展方案, 我们来实现扩展功能:
使用所有的方案结帐,哪种最省钱,就用哪种结帐,
我们在编写测试代码的时候,用到了Mockito这个测试框架,用来模拟前几次活动中的结帐方案, 测试代码如下:

package cn.pconline.harrypotter; 
import java.util.ArrayList;
import java.util.List;

import junit.framework.Assert;

import org.junit.Test;
import org.mockito.Mockito;

public class BestCalculatorTest {
	@Test
	public void testCalculate() throws Exception {
		
		
		//(0--4)单集不够5本
		//(    5	)单集买5本(符合方案2)
		//(	 6	)单集大于5本不够7本  (符合方案2)-- 单集大于40元(5本书的价钱)不够56元(最多7本)
		//(7--12)单集大于等于56元(7本书的价钱)小于100元(最多12本)(符合方案2,3)
		//(13~~ )单集大于100元(符合方案2,3,4)
		
		//(0--5)多集不够6本(方案1)
		
		//(	 6	)多集大于5本少于7本 (方案1,方案2)-- 多集大于等于56元(7本书的价钱)小于100元(最多12本)
			//(有一集大于2本)符合方案1
			//(单集6本)符合方案2
			//(单集5本,另有1集1本)符合方案1,方案2
		//(7 -- 12)多集大于等于7本,少于13本(方案1,方案2,方案3)
			//(有2集)符合方案1,方案3
			//(有单集5本以上,全是单集)符合方案2,方案3
			//(有2集以上书,有一集5本以上,7本以上)符合方案1,方案2,方案3
		// (13~~ )多集大于100元(方案1,方案2,方案3,方案4)
			//(大于12本,有2集以上书)符合方案1,方案3,方案4
			//(大于12本,有5集以上书)符合方案1,方案2,方案3,方案4
		
		//模拟defaultCashier对象
		DefaultCashier defaultCashier = Mockito.mock(DefaultCashier.class);
		List<Book> books = new ArrayList<Book>();
		books.add(new Book(BookType.one));
		books.add(new Book(BookType.one));
		books.add(new Book(BookType.one));
		Mockito.when(defaultCashier.calculate(books)).thenReturn(3);
		
		//模拟sendBookActivity对象
		SendBookActivity sendBookActivity = Mockito.mock(SendBookActivity.class);
		Mockito.when(sendBookActivity.calculate(books)).thenReturn(5);
		
		//模拟sendMoneyActivity对象
		SendMoneyActivity sendMoneyActivity = Mockito.mock(SendMoneyActivity.class);
		Mockito.when(sendMoneyActivity.calculate(books)).thenReturn(7);
		
		//模拟discountCashier对象
		DiscountCashier discountCashier = 
				Mockito.mock(DiscountCashier.class);
		Mockito.when(discountCashier.calculate(books)).thenReturn(9);
		
		//1.没书没方案
		
		BestCalculator bestCalculator = new BestCalculator();
		int price = bestCalculator.calculate(null);
		Assert.assertEquals(0, price);
		
		List<Book> emptyBooks = new ArrayList<Book>();
		price = bestCalculator.calculate(emptyBooks);
		Assert.assertEquals(0, price);
		
		//2.有书没方案
		bestCalculator.setCalculators(null);
		price = bestCalculator.calculate(books);
		Assert.assertEquals(2400, price);
		
		//3.有书有方案
		List<PriceCalculator> calculators = 
				new ArrayList<PriceCalculator>();
		calculators.add(defaultCashier);
		calculators.add(sendBookActivity);
		calculators.add(sendMoneyActivity);
		calculators.add(discountCashier);
		bestCalculator.setCalculators(calculators);
		
		price = bestCalculator.calculate(books);
		Assert.assertEquals(3, price);
		
		//4.没书有方案
		price = bestCalculator.calculate(null);
		Assert.assertEquals(0, price);
		
		price = bestCalculator.calculate(emptyBooks);
		Assert.assertEquals(0, price);
		
	}
}

实现代码

package cn.pconline.harrypotter;

import java.util.ArrayList;
import java.util.List;

public class BestCalculator implements PriceCalculator {

	private List<PriceCalculator> calculators = new ArrayList<PriceCalculator>();
	
	
	public List<PriceCalculator> getCalculators() {
		return calculators;
	}


	public void setCalculators(List<PriceCalculator> calculators) {
		this.calculators = calculators;
	}



	@Override
	public int calculate(List<Book> list) {
		// TODO Auto-generated method stub
		
		// 没有书的时候
		if(list == null || list.isEmpty()){
			return 0;
		}
		int minPrice = 800 * list.size(); // 最低价格
		// 没有方案的时候
		if(calculators == null || calculators.isEmpty()){
			return minPrice;
		}
		
		
		for(PriceCalculator priceCalculator : calculators){
			int price = priceCalculator.calculate(list);
			if (price < minPrice) {
				minPrice = price;
			}
		}
		return minPrice;
	}

}