一.需求
1.请设计一个班级管理模块:学生的数据有姓名,性别,成绩。
功能1:要求打印出全班同学的信息。功能2:要求打印出全班同学的平均成绩。
2.注意!以上业务的实现是有多套方案的,比如:
第一套方案:能打印班级全部学生的信息,能打印班级全部学生的平均分。
第二套方案:能打印出班级内全部学生的信息,包括男女人数,能打印班级的平均分,去掉最高分,最低分。
3.系统可以支持灵活地切换这两套方案。
二.思路分析
我们还是要定义一个student类,用于存放学生的数据,定义成员变量,使用注解如@Data,@AllArgsConstructor,@NoArgsConstructor用于生成getter and setter方法,有参构造器,无参构造器。之后定义一个test类用于测试代码,然后定义一个接口类写出需求中的两个方法名,最后定义两个实现类用于完成方案。我会在每个类的下面讲解代码,帮助读者理解。
1.下面展示student类:
package interfacedemo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class student {
private String name;
private char sex;
private double score;
}
这种代码思想我已经在上次的java实战项目中使用过,是非常普通的思想,相信大家已经掌握。
2.下面展示接口类:
package interfacedemo;
public interface ClassDataInter {
void PrintAllStudentInfos();
void PrintAverageScore();
}
定义一个接口类,里面定义两个抽象方法,方便定义实现类完成需求。
3.下面展示test类:
package interfacedemo;
public class test {
public static void main(String[] args) {
//1.定义学生类,创建学生对象,封装学生数据,才能交给下面的方法处理学生的数据。
//2.准备学生数据,生成班级内10个学生
student[] allstudents = new student[10];
allstudents[0] = new student("王思远", '男', 88.5);
allstudents[1] = new student("李雨桐", '女', 92.0);
allstudents[2] = new student("张浩然", '男', 76.5);
allstudents[3] = new student("刘诗涵", '女', 85.0);
allstudents[4] = new student("陈宇航", '男', 91.5);
allstudents[5] = new student("杨若曦", '女', 94.0);
allstudents[6] = new student("赵天宇", '男', 89.5);
allstudents[7] = new student("黄雅雯", '女', 82.0);
allstudents[8] = new student("周子轩", '男', 95.5);
allstudents[9] = new student("吴欣怡", '女', 78.0);
//3.提供两套业务实现方案,支持灵活切换(解耦合),面向接口编程。
//定义一个接口,写出两个抽象方法名。
//定义第一套实现类,实现接口,实现打印学生信息,实现打印平均分。
//定义第二套实现类,实现接口,实现打印学生信息(男女人数),实现打印平均分去掉最高分最低分。
ClassDataInter cdi = new classDataInterImpl2(allstudents);
cdi.PrintAllStudentInfos();
cdi.PrintAverageScore();
}
}
在此类中,我们定义一个数组student[] allstudents = new student[10];来存放十个学生的信息,这个方法我们在java实战的第一篇已经有所提及,对于java的初学者这样的数组建立思想可能难以理解,这里我再着重分析一下:
int[][] arr = new int [n][n];
这是一个二维数组的定义方法,我们这里的student类是我们定义的类就相当于int,allstudents是我们的数组名就相当于arr,new是固定格式,student还是定义类。
存入10个学生信息之后,我们创立接口的对象,只不过我们再使用实现类1时只需要把后面类名改为实现类1的类名,使用实现类2时只需要把后面类名改为实现类2的类名,这就实现了解耦合。创建好对象后调用方法,完成需求。
4.下面展示两个实现类:
package interfacedemo;
public class classDataInterImpl1 implements ClassDataInter{
private student[] students;
public classDataInterImpl1(student[] students){
this.students = students;
}
@Override
public void PrintAllStudentInfos() {
System.out.println("全班信息如下:");
for (int i = 0; i < students.length; i++) {
student s = students [i];
System.out.println(s.getName() + " " + s.getSex() + " " + s.getScore());
}
}
@Override
public void PrintAverageScore() {
double sum = 0;
for (int i = 0; i < students.length; i++) {
student s = students[i];
sum += s.getScore();
}
System.out.println("全班的平均成绩为:" + sum / students.length);
}
}
package interfacedemo;
public class classDataInterImpl2 implements ClassDataInter{
private student[] students;
public classDataInterImpl2(student[] students){
this.students = students;
}
@Override
public void PrintAllStudentInfos() {
System.out.println("学生信息如下");
int maleCount = 0;
for (int i = 0; i < students.length; i++) {
student s = students[i];
System.out.println(s.getName() + " " + s.getSex() + " " + s.getScore());
if (s.getSex() == '男'){
maleCount++;
}
}
System.out.println("男学生人数:" + maleCount);
System.out.println("女学生人数:" + (students.length - maleCount));
}
@Override
public void PrintAverageScore() {
System.out.println("平均分如下:");
student s1 = students[0];
double sum = s1.getScore();
double min = s1.getScore();
double max = s1.getScore();
for (int i = 1; i < students.length; i++) {
student s = students[i];
sum += s.getScore();
if (s.getScore() > max){
max = s.getScore();
}
if (s.getScore() < min){
min = s.getScore();
}
}
System.out.println("最高分:" + max);
System.out.println("最低分:" + min);
System.out.println("平均分:" + (sum - max - min) / (students.length - 2));
}
}
这两个实现类都是都是先封装test类中的定义的那个数组,重命名为students,在下面类方法中进行操作。重写接口中的方法后,根据需求进行编程,应该难度不算很大。对于java初学者来说,实现类2的第二个方法可能较难,我重点分析一下。因为需要找出学生中的最高分,最低分,我们需要一个擂台法,先将第一个学生的分数设为最高分和最低分,如果在遍历数组的时候发现有高于这个学生的分数,立即让max等于这个分数,而最小值同理。我们不能直接将max或min赋初值为0,因为会有风险使min值无法获得真正的最小值,而应该使用擂台思想。
三.运行结果
调用实现类1:
调用实现类2: