要求:
1、第一阶段目标:重构四则运算-- 能把计算的功能封装起来,通过API 接口调用计算方法。
定义一个计算核心类:把四则运算的计算功能包装在一个模块中 (这个模块可以是一个类 Class, 一个DLL等等)。
“计算核心”模块和调用类它的其他模块之间是什么关系呢?
它们要通过一定的API (Application Programming Interface) 来和其他模块交流。
这个API 接口应该怎么设计呢? 可以从下面的最简单的接口开始:
Calc()
这个Calc 函数接受字符串的输入(字符串里就是运算式子,例如 “ 5+3.5“, “7/8 – 3/8 ”, “3 + 90 * (-0.3)“ 等等),这个模块的返回值是一个字符串,例如,前面几个例子的结果就是 ( ”17.5“, “ 1/2”, “-24“).
2 第二阶段目标 - 通过测试程序和API 接口测试其简单的加减乘除功能。并能看到代码覆盖率。
可以扩展 Calc() 的定义,让它接受一个新的参数 “precision”, 或者可以启用一个新的函数 Setting()。
最多4 个运算符
数值范围是 -1000 到 1000
精度是小数点后两位
怎么通过API 告诉我们的模块呢? 我们当然可以用函数的参数直接传递,但是参数的组合很多,怎么定义好参数的规范呢? 建议大家考虑用 XML 来传递这些参数。
增加了新的Setting() 函数之后,要让模块支持这样的参数,同时,还要保证原来的各个测试用例继续正确地工作。
3第三阶段目标 – 定义异常处理。
如果输入是有错误的,例如 “1 ++ 2”, 在数值范围是 -1000 .. 1000 的时候,传进去 “10000 + 32768 * 3”, 或者是 “ 248.04 / 0” 怎么办? 怎么告诉函数的调用者 “你错了”? 把返回的字符串定义为 “-1” 来表示? 那么如果真的计算结果是 “-1” 又怎么处理呢?
建议这个时候,要定义各种异常 (Exception), 让 Core 在碰到各种异常情况的时候,能告诉调用者 - 你错了! 当然,这个时候,同样要进行下面的增量修改:
定义要增加什么功能 - 例如:支持 “运算式子格式错误” 异常,写好测试用例,传进去一个错误的式子,期望能捕获这个 异常。 如果没有,那测试就报错。
在 Core 模块中实现这个功能,测试这个功能, 同时测试所有以前的功能,保证以前的功能还能继续工作 (没有 regression), 确认功能完成,继续下一个功能。
//运算类封装 package avshabi; import java.util.StringTokenizer; public class Calculator { int numerator; // 分子 int denominator; // 分母 Calculator(){ } Calculator(int a,int b){ if(a == 0){ numerator = 0; denominator = 1; } else{ setNumeratorAndDenominator(a,b); } } void setNumeratorAndDenominator(int a, int b){ // 设置分子和分母 int c = f(Math.abs(a),Math.abs(b)); // 计算最大公约数 numerator = a / c; denominator = b / c; if(numerator<0 && denominator<0){ numerator = - numerator; denominator = - denominator; } } int getNumerator(){ return numerator; } int getDenominator(){ return denominator; } int f(int a,int b){ // 求a和b的最大公约数 if(a < b){ int c = a; a = b; b = c; } int r = a % b; while(r != 0){ a = b; b = r;; r = a % b; } return b; } Calculator add(Calculator r){ // 加法运算 int a = r.getNumerator(); int b = r.getDenominator(); int newNumerator = numerator * b + denominator * a; int newDenominator = denominator * b; Calculator result = new Calculator(newNumerator,newDenominator); return result; } Calculator sub(Calculator r){ // 减法运算 int a = r.getNumerator(); int b = r.getDenominator(); int newNumerator = numerator * b - denominator * a; int newDenominator = denominator * b; Calculator result = new Calculator(newNumerator,newDenominator); return result; } Calculator muti(Calculator r){ // 乘法运算 int a = r.getNumerator(); int b = r.getDenominator(); int newNumerator = numerator * a; int newDenominator = denominator * b; Calculator result = new Calculator(newNumerator,newDenominator); return result; } Calculator div(Calculator r){ // 除法运算 int a = r.getNumerator(); int b = r.getDenominator(); int newNumerator = numerator * b; int newDenominator = denominator * a; Calculator result = new Calculator(newNumerator,newDenominator); return result; } // 封装了具体运算,主要为对输入进行转换,对输出封装 public static void compute(String data1,String operation,String data2){ StringTokenizer fenxi = new StringTokenizer(data1,"/"); int data1_1 = Integer.parseInt(fenxi.nextToken()); int data1_2 = Integer.parseInt(fenxi.nextToken()); fenxi = new StringTokenizer(data2,"/"); int data2_1 = Integer.parseInt(fenxi.nextToken()); int data2_2 = Integer.parseInt(fenxi.nextToken()); Calculator r1 = new Calculator(data1_1,data1_2); Calculator r2 = new Calculator(data2_1,data2_2); Calculator result; int a,b; if(operation.equals("+")){ result = r1.add(r2); a = result.getNumerator(); b = result.getDenominator(); System.out.println(data1+" "+operation+" " +data2+" = " + a + "/" + b); } if(operation.equals("-")){ result = r1.sub(r2); a = result.getNumerator(); b = result.getDenominator(); System.out.println(data1+" "+operation+" " +data2+" = " + a + "/" + b); } if(operation.equals("*")){ result = r1.muti(r2); a = result.getNumerator(); b = result.getDenominator(); System.out.println(data1+" "+operation+" " +data2+" = " + a + "/" + b); } if(operation.equals("/")){ result = r1.div(r2); a = result.getNumerator(); b = result.getDenominator(); System.out.println(data1+" "+operation+" " +data2+" = " + a + "/" + b); } } } // 测试类 package avshabi; import java.util.Scanner; public class TestCal { public static void main(String[] args) { // TODO Auto-generated method stub // 用户输入两分数和运算符 Scanner input = new Scanner(System.in); System.out.println("请用户输入第一个分数(格式a/b)"); String data1 = input.next(); System.out.println("请用户输入要进行运算的运算符(+-*/)"); String operation = input.next(); System.out.println("请用户输入第二个分数(格式c/d)"); String data2 = input.next(); // 根据用户输入进行具体运算 Calculator cal = new Calculator(); System.out.println("运算结果为:"); cal.compute(data1, operation, data2); // } } } //JUint 应用测试举例 package avshabi; import static org.junit.Assert.*; import org.junit.Test; public class CalculatorTest { @Test public void testAdd() { Calculator cal = new Calculator(); cal.add(cal); } @Test public void testSub() { Calculator cal = new Calculator(); cal.sub(cal); } @Test public void testMuti() { Calculator cal = new Calculator(); cal.muti(cal); } @Test public void testDiv() { Calculator cal = new Calculator(); cal.div(cal); } @Test public void testCompute() { Calculator cal = new Calculator(); cal.compute("1/2", "+", "2/3"); cal.compute("1/2", "-", "2/3"); cal.compute("1/2", "*", "2/3"); cal.compute("1/2", "/", "2/3"); } }
运行截图: