某学校为响应国家教学评估体制改革,现预备按表 Tab1.1 所示方案将百分制成绩转化为等级制成绩,试给出转换办法。
Tab1.1方案实现:
package transf_CentesimalSys_to_GradationSys;
import java.util.Scanner;
/**
* @see 百分制转等级制
* @version 1.0
* @author JustBeGeek
*/
public class Transform_1 {
public static void main(String[] args){
Scanner input=new Scanner(System.in);
System.out.println("请输入你的成绩:");
int mark=input.nextInt();
String grade="";
/*————————————————————————-*/
if(mark>=90)
grade+='A';
else if(mark>=80)
grade+='B';
else if(mark>=70)
grade+='C';
else if(mark>=60)
grade+='D';
else
grade+='E';
/*————————————————————————-*/
System.out.println("在转换方案(Ⅰ)下,您的成绩是:"+grade);
}
}
若该学校获悉市教育局预备按方案 Tab1.2 统一实施 百分制成绩转等级制成绩 改革,试给出对应转换办法。
分析:Tab1.2 方案 较 Tab1.1 方案 改变之处仅为每个等级对应的分数段发生改变, 而程序 Transform_1 为适应 Tab1.2 方案须修改其多路比较中的所有分界值常量(90、80以及70等),而这样的修改幅度较大,容易产生bugs,且适应性差(在下一次对应分数段改变时仍需要冒此类风险进行修改)。也就是说,转换方案的每一次变动都将令程序 Transform_1 不得不进行大幅度修改以适应新方案,而这样的修改仅能暂时维持程序满足方案要求。究其原因,我们不难发现是由于程序 Transform_1 在其多路比较中直接引入分界值常量,而分界值在转换方案变动时是不稳定的。
方案:将分界值常量有序存储于数组中,在多路比较中采用存储了相应分界值常量的数组分量作为比较基准;发生对应分数段改变时仅需更新数组中的有序常量集。
Tab1.2 方案实现(等级名称亦可调整):
package transf_CentesimalSys_to_GradationSys;
import java.util.Scanner;
/**
* @see 百分制转等级制
* @version 2.0
* @author JustBeGeek
*/
public class Transform_2 {
private static final int[] GRADATION={85,75,65,55};
private static final String[] GRADE={"A","B","C","D","E"};
public static void main(String[] args){
Scanner input=new Scanner(System.in);
System.out.println("请输入你的成绩:");
int mark=input.nextInt();
String grade="";
/*————————————————————————-*/
if(mark>=GRADATION[0])
grade+=GRADE[0];
else if(mark>=GRADATION[1])
grade+=GRADE[1];
else if(mark>=GRADATION[2])
grade+=GRADE[2];
else if(mark>=GRADATION[3])
grade+=GRADE[3];
else
grade+=GRADE[4];
/*————————————————————————-*/
System.out.println("在转换方案(Ⅱ)下,您的成绩是:"+grade);
}
}
该学校为更详细了解学生成绩分布,现准备在市教育局方案基础上制定内部方案 Tab1.3,试给出转换办法。
分析:Tab1.2 到 Tab1.3 的方案迁移,造成等级划分更细,即出现了更多的等级。若为适应新的内部方案而对 程序 Transform_2 进行维护,我们发现其工作量较“ 程序 Transform_1 为适应 Tab1.1 至Tab1.2 的迁移维护”更大也更繁琐,这样的维护与专门为 Tab1.3 构建新程序有过之而无不及,于是,我决定进行第二次通用化处理,即如何消除常量集规模对程序多路选择路数的影响?
方案:①数组有序存储分界值常量集;②采用循环测试代替多路选择测试。
Tab1.3 方案实现:
package transf_CentesimalSys_to_GradationSys;
import java.util.Scanner;
/**
* @see 百分制转等级制
* @version 3.0
* @author JustBeGeek
*/
public class Transform_3 {
/**
* @see 方案集
*
*/
/*Tab1.2方案*/
private static final int[] GRADATION1_2={85,75,65,55};
private static final String[] GRADE1_2= {"A","B","C","D","E"};
/*Tab1.3方案*/
private static final int[] GRADATION1_3={95,85,80,75,65,60,55};
private static final String[] GRADE1_3={"A+","A-","B+","B-","C+","C-","D+","D-","E"};
public static void main(String[] args){
Scanner input=new Scanner(System.in);
System.out.println("请输入你的成绩:");
int mark=input.nextInt();
String grade="";
/*————————————————————————-*/
boolean inner=false;//此变量标定是否按内部方案执行,默认按市教育局方案执行
if(inner)
grade+=whichGrade(GRADATION1_2,GRADE1_2,mark);
else
grade+=whichGrade(GRADATION1_3,GRADE1_3,mark);
/*————————————————————————-*/
System.out.println("在转换方案(Ⅲ)下,您的成绩是:"+grade);
}
public static String whichGrade(int[] gradation,String[] grade,int mark){
int i=0;
for(;i<gradation.length;i++){
if(mark>=gradation[i])
break;
}
return grade[i];
}
}
分析:在维护程序 Transform_3 时,我们发现其用两个数组分别存储同一方案中的两组常量集(分数分界点集、等级符号集),并在 函数 whichGrade 中实现由分数分界点集到等级符号集的映射的设计 人为地割裂了同属一个方案的两组关联数据,造成它们间的映射关系不够显著(模糊了函数构造与函数求值),而且维护时更需十分注意两组关联赋值的顺序是否对应。为了使维护程序更加直观、方便,我决定采用了以下方法改造:①构造关系节点 Mapping ;② 利用 Mapping 型数组独立存储各转换方案(构造函数);③ 函数 whichGrade 直接将方案( Mapping 型数组)作为参数,并根据方案找到分数对应的等级(函数求值)。
Tab1.3 方案改进实现:
package transf_CentesimalSys_to_GradationSys;
import java.util.Scanner;
import transf_CentesimalSys_to_GradationSys.Mapping;
/**
* @see 百分制转等级制
* @version 3.1
* @author JustBeGeek
*/
public class Transform_3_1 {
/**
* @see 方案集
* @see 方案:分界值常量集到等级常量集的关系。
*/
/*Tab1.2方案*/
private static final Mapping[] Tab1_2={
new Mapping(85,"A"),new Mapping(75,"B"),
new Mapping(65,"C"),new Mapping(55,"D"),
new Mapping(0,"E"),
};
/*Tab1.3方案*/
private static final Mapping[] Tab1_3={
new Mapping(95,"A+"),new Mapping(85,"A-"),
new Mapping(80,"B+"),new Mapping(75,"B-"),
new Mapping(70,"C+"),new Mapping(65,"C-"),
new Mapping(60,"D+"),new Mapping(55,"D-"),
new Mapping(0,"E")};
public static void main(String[] args){
Scanner input=new Scanner(System.in);
System.out.println("请输入你的成绩:");
int mark=input.nextInt();
String grade="";
/*————————————————————————-*/
boolean inner=false;//此变量标定是否按内部方案执行,默认按市教育局方案执行
if(inner)
grade+=whichGrade(Tab1_2,mark);
else
grade+=whichGrade(Tab1_3,mark);
/*————————————————————————-*/
System.out.println("在转换方案(Ⅲ)下,您的成绩是:"+"grade");
}
/**
* @see 分数mark按方案schem执行转换
* @param schem 方案
* @param mark 分数
* @return 等级
*/
private static String whichGrade(Mapping[] schem,int mark){
int i=0;
for(;i<schem.length;i++){
if(mark>=schem[i].getGradation())
break;
}
return schem[i].getGrade();
}
}
调用类:
package transf_CentesimalSys_to_GradationSys;
/**
* @see 关系节点
* @author JustBeGeek
*/
public class Mapping{
private int gradation;
private String grade;
public Mapping(int gradation,String grade){
this.gradation=gradation;
this.grade=grade;
}
public int getGradation(){
return gradation;
}
public String getGrade(){
return grade;
}
}