学生信息管理系统
学生信息管理系统需求说明
需求分析
业务功能梳理
- StudentManagement实现增删改查功能
- 控制端输入
- 控制端打印相关输出
实现思路
代码实现
流程图
基本实现
相关知识
- 封装
- 面向对象编程
- 错误与异常
实现代码
import entity.Student;
import enums.SexEnum;
import exceptions.StudentIdAlreadyExitException;
import exceptions.StudentIdNotExitException;
import exceptions.StudentSexInputException;
import java.util.*;
public class StudentManagement {
private static Map<Integer, Student> students;
public void initData() {
students = new HashMap<>();
}
public void addStudent(Integer id, String name, String sex) {
SexEnum se = null;
// 判断学生id
if (students.containsKey(id)) {
throw new StudentIdAlreadyExitException();
}
//判断性别
if (sex.equals(SexEnum.man.getChineseName())) {
se = SexEnum.man;
} else if (sex.equals(SexEnum.female.getChineseName())) {
se = SexEnum.female;
} else {
throw new StudentSexInputException();
}
students.put(id, new Student(id, name, se));
System.out.println("学生添加成功!");
}
public void deleteStudent(Integer id) {
// 判断学生是否存在
if (students.containsKey(id)) {
students.remove(id);
} else {
throw new StudentIdNotExitException();
}
System.out.println("学生删除成功!");
}
public Student getStudent(Integer id) {
if (!students.containsKey(id)) {
throw new StudentIdNotExitException();
}
return students.get(id);
}
public List<Student> getStudentAll() {
// 返回所有学生
return new ArrayList<>(students.values());
}
public void show(Integer studentId) {
// 展示学生信息
System.out.println(this.getStudent(studentId));
}
public void showAll() {
// 打印所有学生
List<Student> studentAll = this.getStudentAll();
for(int i = 0; i<this.getStudentAll().size(); i++){
System.out.print(i+1+"."+studentAll.get(i));
}
}
public void run() {
//初始化数据
this.initData();
final Integer SHOW_FLAG = 1;
final Integer ADD_FLAG = 2;
final Integer DEL_FLAG = 3;
final Integer EXIT_FLAG = 4;
System.out.println("-------欢迎来到学员信息管理系统-------");
Scanner scanner = new Scanner(System.in);
while (true) {
try {
System.out.println("\n\n1.根据学号查看学员信息\n2.添加学员\n3.根据学号删除学员后,查看所有学员信息\n4.退出系统\n请输入你的选择");
Integer fun = scanner.nextInt();
if (fun.equals(SHOW_FLAG)) {
System.out.println("请输入学生id");
int studentId = scanner.nextInt();
this.show(studentId);
} else if (fun.equals(ADD_FLAG)) {
System.out.println("请输入学生id");
int studentId = scanner.nextInt();
// 处理回车
scanner.nextLine();
System.out.println("请输入学生姓名");
String studentName = scanner.nextLine();
System.out.println("请输入学生性别");
String studentSex = scanner.nextLine();
this.addStudent(studentId, studentName, studentSex);
} else if (fun.equals(DEL_FLAG)) {
System.out.println("请输入学生id");
int studentId = scanner.nextInt();
this.deleteStudent(studentId);
this.showAll();
} else if (fun.equals(EXIT_FLAG)) {
System.exit(0);
} else {
System.out.println("无该操作选项,请重新选择");
}
}catch (RuntimeException e) {
System.out.println(e.getMessage());
}
}
}
public static void main(String[] args) {
new StudentManagement().run();
}
}
单元测试
package student;
import entity.Student;
import enums.SexEnum;
import exceptions.StudentIdNotExitException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
public class StudentManagementTest {
StudentManagement studentManagement;
@Before
public void setUp() {
studentManagement = new StudentManagement();
studentManagement.initData();
}
@Test
public void testAddStudent() {
Integer id = 1;
String name = "Tom";
String sex = "男";
studentManagement.addStudent(id, name, sex);
Student student = studentManagement.getStudent(id);
Assert.assertEquals(id, student.getId());
Assert.assertEquals(name, student.getName());
Assert.assertEquals(SexEnum.man, student.getSex());
}
@Test(expected = StudentIdNotExitException.class)
public void testDeleteStudent() {
Integer id = 1;
String name = "Tom";
String sex = "男";
studentManagement.addStudent(id, name, sex);
studentManagement.deleteStudent(id);
Student student = studentManagement.getStudent(id);
Assert.assertNull(student);
}
@Test
public void testGetStudent() {
Integer id = 1;
String name = "Tom";
String sex = "男";
studentManagement.addStudent(id, name, sex);
Student student = studentManagement.getStudent(id);
Assert.assertEquals(id, student.getId());
Assert.assertEquals(name, student.getName());
Assert.assertEquals(SexEnum.man, student.getSex());
}
@Test
public void testGetStudentAll() {
Integer id1 = 1;
String name1 = "Tom";
String sex1 = "男";
Integer id2 = 2;
String name2 = "Jane";
String sex2 = "女";
studentManagement.addStudent(id1, name1, sex1);
studentManagement.addStudent(id2, name2, sex2);
List<Student> students = studentManagement.getStudentAll();
Assert.assertEquals(2, students.size());
}
}
代码重构与优化
相关知识点
- 接口
- 多态
面向接口编程
但是上面的核心实现都是放在同一个类里,这大大的提高了维护难度,而且导致代码可测性下降。
进行改造可以先根据函数功能以及单一职责进行拆分,分别拆为学员管理以及展示客户端,通过接口定义行为完成编程
面向接口编程优点:
- 实现多态性:接口定义了一组公共的方法,而不关心具体的实现细节。通过使用接口,可以在不改变代码结构的情况下,轻松地切换不同的实现类。这样可以实现代码的高度可扩展性和可维护性,同时也方便进行单元测试和模块化开发。
- 减少耦合性:面向接口编程能够降低组件和模块之间的耦合度。
- 提高代码的可读性和可维护性:接口定义了一组易于理解和调用的方法。
- 支持并行开发:在多人协作开发时,代码的接口也提供了开发者之间的约定,统一了代码的规范和实现方式。不同开发人员可以独立开发实现类,而不需要等待其他模块的开发完成。
类关系图
单元测试
最后我们可以对核心功能进行单元测试
public class StudentManagerTest {
StudentManager studentManager;
@Before
public void setUp() {
studentManager = new StudentManagerMemoryImpl();
studentManager.initData();
}
@Test
public void testAddStudent() {
Integer id = 1;
String name = "Tom";
String sex = "男";
studentManager.addStudent(id, name, sex);
Student student = studentManager.getStudent(id);
Assert.assertEquals(id, student.getId());
Assert.assertEquals(name, student.getName());
Assert.assertEquals(SexEnum.man, student.getSex());
}
@Test(expected = StudentIdNotExitException.class)
public void testDeleteStudent() {
Integer id = 1;
String name = "Tom";
String sex = "男";
studentManager.addStudent(id, name, sex);
studentManager.deleteStudent(id);
Student student = studentManager.getStudent(id);
Assert.assertNull(student);
}
@Test
public void testGetStudent() {
Integer id = 1;
String name = "Tom";
String sex = "男";
studentManager.addStudent(id, name, sex);
Student student = studentManager.getStudent(id);
Assert.assertEquals(id, student.getId());
Assert.assertEquals(name, student.getName());
Assert.assertEquals(SexEnum.man, student.getSex());
}
@Test
public void testGetStudentAll() {
Integer id1 = 1;
String name1 = "Tom";
String sex1 = "男";
Integer id2 = 2;
String name2 = "Jane";
String sex2 = "女";
studentManager.addStudent(id1, name1, sex1);
studentManager.addStudent(id2, name2, sex2);
List<Student> students = studentManager.getStudentAll();
Assert.assertEquals(2, students.size());
}
}
总结
- 熟悉封装、多态面向对象知识点
- 通过面向接口编程降低了耦合度,提高代码的可重用性等
- 更好的支持单元测试:接口编程可以更方便地进行单元测试。通过定义接口,可以很容易地创建模拟对象或者使用桩对象来进行测试,从而验证代码的正确性。
总的来说,接口编程提供了一种灵活、可扩展和可维护的编程方式,可以提高代码质量和开发效率,适用于大型项目和团队协作。