美文网首页
Java-----基于面向对象开发学生管理系统

Java-----基于面向对象开发学生管理系统

作者: 会写代码的小猿猴 | 来源:发表于2021-12-15 17:09 被阅读0次

    1、大致功能

    开发一个简单的系统,该系统可以对学生进行增删改查(CRUD);

    2、需求分析

    • 添加学生:键盘录入学生信息(学号,姓名,年龄,出生日期),使用数组存储学生信息,要求学号不能重复。
    • 删除学生:键盘录入要删除的学生学号,将学生从数组中移除
    • 修改学生:键盘录入要修改学生的学号和修改后的信息,将数组中学生的信息修改
    • 遍历学生: 将所有的学生信息输出到控制台

    3、基本类的创建

    在开发中,我们要学会对很多类进行分类思想,不能把所有的类一股脑塞到一个包里面,下面是我对这个小demo类的分类分包的详情。


    image.png

    搭建以后目录结构如下所示:


    image.png

    4、菜单搭建

    主要分为主菜单搭建和学生管理系统菜单搭建
    先来看主菜单搭建,主菜搭建在程序入口InfoManagerEntry里面进行搭建
    主菜单搭建:

    public class InfoManagerEntry {
        public static void main(String[] args) {
            Scanner sc=new Scanner(System.in);
            //主菜单搭建
            while(true){
                System.out.println("----------欢迎来到学生老师管理系统----------");
                System.out.println("请输入您的选择:1、学生管理  2、老师管理  3、退出");
                String choice = sc.next();
                switch(choice){
                    case "1":
                        //开启学生管理系统
                        StudentController studentcontroller=new StudentController();
                        studentcontroller.start();
                        break;
                    case "2":
                        System.out.println("老师管理");
                        break;
                    case "3":
                        System.out.println("感谢您的使用");
                        //退出当前正在运行的JVM虚拟机,关闭程序
                        System.exit(0);
                        break;
                    default:
                        System.out.println("您的输入有误,清重新输入");
                        break;
                }
            }
    
        }
    }
    

    上面代码中我们输入1进入学生管理系统,执行StudentController 的Start()方法,StudentController 代码实现如下:

    public class StudentController {
        //该方法用于开启学生管理系统,展示学生管理系统菜单
        public void start() {
            Scanner sc=new Scanner(System.in);
            studentLoop:while(true){
                System.out.println("----------欢迎来到学生管理系统----------");
                System.out.println("请输入您的选择:1、添加学生  2、删除学生  3、修改学生  4、查找学生  5、退出");
                String choice = sc.next();
                switch(choice){
                    case "1":
                        System.out.println("添加");
                        break;
                    case "2":
                        System.out.println("删除");
                        break;
                    case "3":
                        System.out.println("修改");
                        break;
                    case "4":
                        System.out.println("查找");
                        break;
                    case "5":
                       /* 这里是退出这个循环而不是退出JVM虚拟机,所以不能用System.exit(),
                        这里的做法是给循环取个名字叫studentLoop,然后输入5后break这个循环就可以了*/
                        System.out.println("感谢您使用学生管理系统,再见!");
                        break studentLoop;
                    default:
                        System.out.println("您的输入有误,清重新输入");
                        break;
                }
            }
    
        }
    }
    

    到这里基本的菜单搭建就完成了,接下来我们把菜单里面的功能一个个实现出来。

    5、添加功能的实现

    添加功能分析(主要着重分包分类思想分析,每个类的分工合作)


    image.png

    这里需要明确不同包下的每个类的作用,我在第三步中已经给出了每个类具体负责的事务。大家自己领悟就好。
    代码实现,如上图所示,在上图三个类中都有一个addStudent()方法,每个方法需要实现不同的功能,我们先来看StudentController里面的addStudent方法,图中说明该方法主要实现以下功能:

    • 方法中接受用户输入的信息
    • 将学生信息封装为学生对象传递给StudentService
    • 接收方法的boolean类型返回值,根据结果在控制台打印添加成功\添加失败
      那我们就根据这三点要求来创建addStudent方法。
     public void addStudent() {
            //1、接收用户输入的信息
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入学生id:");
            String id = sc.next();
            System.out.println("请输入学生姓名:");
            String name = sc.next();
            System.out.println("请输入学生年龄:");
            String age = sc.next();
            System.out.println("请输入学生生日:");
            String birthday = sc.next();
            //2、将学生信息封装为学生对象传递给StudentService
            Student stu = new Student(id, name, age, birthday);
            //3、将学生对象传递给StudentService中的addStudent方法
            StudentService studentservice = new StudentService();
            boolean result = studentservice.addStudent(stu);
            //4、接收方法的boolean类型返回值,根据结果在控制台打印添加成功\添加失败
            if (result) {
                System.out.println("添加成功");
            } else {
                System.out.println("添加失败");
            }
    
        }
    

    然后在用户输入1时调用就可以了,

      case "1":
                        addStudent();
                        break;
    

    在上面这个方法中需要接收StudentService 中的addStudent方法返回的结果,再来看看StudentService 中的addStudent方法,上面图中已经给出这个方法需要实现的功能,直接照着写就好了。

    //1.将接受到的学生对象,传递给StudentDao
    //2.接受方法的boolean返回值将结果返还给StudentC ontroller
     public boolean addStudent(Student stu) {
            StudentDao studentdao = new StudentDao();
            return studentdao.addStudent(stu);
        }
    

    这个方法又用到了StudentDao 里面的addStudent方法,也是一样的,根据需求在studentdao内部实现该方法就可以了。代码如下:

    public boolean addStudent(Student stu) {
            //1.创建Student学生数组长度为5
            Student[] students = new Student[5];
            // 2.将接受到的学生对象添加到数组中
            int index = -1;
            for (int i = 0; i < students.length; i++) {
                Student student = students[i];
                if (student == null) {
                    index = i;
                    break;
                }
            }
            //3.返回是否添加成功的boolean类型值
            if (index == -1) {
                return false;
            } else {
                students[index] = stu;
                return true;
            }
        }
    

    但是上面的代码还有缺陷,比如我们输入一个已经存在的学生,他也会直接添加进去,所以我们需要添加判断学生是否存在的逻辑代码,这部分逻辑代码同样使用分包分类的思想,先来看一个分析图:


    image.png

    判断id是否存在属于业务逻辑代码,应该在StudentService中实现,接收学生id属于和用户打交道,在StudentController中实现,实现判断时需要拿到现在数组中的所有学生对象,这个属于访问存贮数据,应该在StudentDao中实现,这里我直接把每个类的完整代码贴出来了。
    StudentController:

    public class StudentController {
        //该方法用于开启学生管理系统,展示学生管理系统菜单
        public void start() {
            Scanner sc = new Scanner(System.in);
            studentLoop:
            while (true) {
                System.out.println("----------欢迎来到学生管理系统----------");
                System.out.println("请输入您的选择:1、添加学生  2、删除学生  3、修改学生  4、查找学生  5、退出");
                String choice = sc.next();
                switch (choice) {
                    case "1":
                        addStudent();
                        break;
                    case "2":
                        System.out.println("删除");
                        break;
                    case "3":
                        System.out.println("修改");
                        break;
                    case "4":
                        System.out.println("查找");
                        break;
                    case "5":
                       /* 这里是退出这个循环而不是退出JVM虚拟机,所以不能用System.exit(),
                        这里的做法是给循环取个名字叫studentLoop,然后输入5后break这个循环就可以了*/
                        System.out.println("感谢您使用学生管理系统,再见!");
                        break studentLoop;
                    default:
                        System.out.println("您的输入有误,清重新输入");
                        break;
                }
            }
    
        }
    
    
        public void addStudent() {
            //1、接收用户输入的信息
            StudentService studentservice = new StudentService();
            Scanner sc = new Scanner(System.in);
            String id;
            while (true) {
                System.out.println("请输入学生id:");
                id = sc.next();
                boolean flag = studentservice.isExits(id);
                if (flag) {
                    System.out.println("学号已被占用,请重新输入");
                } else {
                    break;
                }
            }
            System.out.println("请输入学生姓名:");
            String name = sc.next();
            System.out.println("请输入学生年龄:");
            String age = sc.next();
            System.out.println("请输入学生生日:");
            String birthday = sc.next();
            //2、将学生信息封装为学生对象传递给StudentService
            Student stu = new Student(id, name, age, birthday);
            //3、将学生对象传递给StudentService中的addStudent方法
    
            boolean result = studentservice.addStudent(stu);
            //4、接收方法的boolean类型返回值,根据结果在控制台打印添加成功\添加失败
            if (result) {
                System.out.println("添加成功");
            } else {
                System.out.println("添加失败");
            }
    
        }
    }
    

    StudentService:

    public class StudentService {
        StudentDao studentdao = new StudentDao();
        public boolean addStudent(Student stu) {
            return studentdao.addStudent(stu);
        }
    
        public boolean isExits(String id) {
            Student[] stus = studentdao.findAllAtudents();
            boolean exits = false;
            for (int i = 0; i < stus.length; i++) {
                Student student = stus[i];
                if (student != null && student.getId().equals(id)) {
                    exits = true;
                    break;
                }
            }
            return exits;
        }
    }
    

    StudentDao:

    public class StudentDao {
        //1.创建Student学生数组长度为5
        Student[] students = new Student[5];
        public boolean addStudent(Student stu) {
            // 2.将接受到的学生对象添加到数组中
            int index = -1;
            for (int i = 0; i < students.length; i++) {
                Student student = students[i];
                if (student == null) {
                    index = i;
                    break;
                }
            }
            //3.返回是否添加成功的boolean类型值
            if (index == -1) {
                return false;
            } else {
                students[index] = stu;
                return true;
            }
        }
    
        public Student[] findAllAtudents() {
            return students;
        }
    }
    

    然后我在测试的时候发现我先添加一个学生,然后在添加同样的学生还是能添加进去,这是为什么呢,其实原因就是因为第二次添加的时候它会重新创建一个对象,和第一次添加的对象不是同一个导致他不能判断是否重复,怎么解决呢?这里就要用到Static关键字了,下面是static关键字的一些知识点。


    image.png

    在内存中有一块静态存储位置专门负责存储status修饰的内容,随着类的加载它会一直存在。
    使用Static需要注意的几点:

    • 静态方法内部只能访问静态成员(成员变量、成员方法)
      原因分析:静态的内容随着类的加载而加载,非静态内容必须在创建对象之后才能使用,所以当静态内容存在时可能非静态内容还没有,所以静态方法内部只能访问静态成员。
    • 非静态成员方法可以使用静态成员变量,也可以使用非静态成员变量。
    • 静态方法中没有this关键字。
      原因分析:this代表当前对象的引用,但是静态存在时可能还没有创建对象,所以没有this关键字。
      到这里问题就很清楚了,因为我们从StudentDao拿到的学生数组和第一次添加的不是同一个,所以只需要把StudentDao中的学生数组改为Static变量就可以了
    public class StudentDao {
        //1.创建Student学生数组长度为5
        public static Student[] students = new Student[5];
        public boolean addStudent(Student stu) {
            // 2.将接受到的学生对象添加到数组中
            int index = -1;
            for (int i = 0; i < students.length; i++) {
                Student student = students[i];
                if (student == null) {
                    index = i;
                    break;
                }
            }
            //3.返回是否添加成功的boolean类型值
            if (index == -1) {
                return false;
            } else {
                students[index] = stu;
                return true;
            }
        }
    
        public Student[] findAllAtudents() {
            return students;
        }
    }
    

    学号重复问题测试效果如下:


    image.png

    到这里整个添加方法就实现了,这样层层嵌套就是为了说明一个分包分类思想,哪些功能需要由哪个类来实现,放在哪个包下,在实际开发中也是需要这样来降低程序的耦合度,这样便于维护代码,要是全部揉成一坨后期维护会非常非常困难,这一点博主也是深有体会。

    6、查看学生代码实现

    同样的先来分析每个类需要完成的工作:


    image.png

    这个很简单了,参照开头给出的分类分包思想图进行分析就可以了。
    代码实现(根据上图步骤创建每个类中的方法)
    StudentController中的findAllStudent方法:

       private void findAllAtudents() {
            Student[] stus=studentservice.findAllStudents();
            if (stus==null){
                System.out.println("系统内暂无学生信息,请添加重试");
                return;
            }else{
                for (int i = 0; i < stus.length; i++) {
                    Student stu3=stus[i];
                    if (stu3!=null) {
                        System.out.println("学号:" + stus[i].getId() + "姓名:" + stus[i].getName() + "年龄:" + stus[i].getAge() + "生日:" + stus[i].getBirthday());
                    }
                }
            }
        }
    

    StudentService中的findAllStudent方法:

      public Student[] findAllStudents() {
            Student[] stus = studentdao.findAllAtudents();
            boolean flag = false;
            for (int i = 0; i < stus.length; i++) {
                Student stus1 = stus[i];
                if (stus1 != null) {
                    flag = true;
                }
            }
            if (flag) {
                return stus;
            } else {
                return null;
            }
        }
    

    StudentDao中的findAllStudents方法:

    public Student[] findAllAtudents() {
            return students;
        }
    

    测试结果:


    image.png

    7、删除学生代码实现

    和前面一样,先来一张思路分析图:


    image.png

    StudentController中的deleteStudentById方法:

      public void deleteStudentById(){
            System.out.println("请输入需要删除的学生id");
            Scanner sc=new Scanner(System.in);
            String id=sc.next();
            boolean exits = studentservice.isExits(id);
            if (exits){
                boolean b = studentservice.deleteStudentById(id);
                if (b){
                    System.out.println("删除成功");
                }else{
                    System.out.println("删除失败");
                }
            }else{
                System.out.println("没有该名学生,不需要删除");
            }
        }
    

    StudentService中的deleteStudentById方法:

     public boolean deleteStudentById(String id) {
            boolean isDelete=studentdao.deleteStudentById(id);
            return isDelete;
        }
    

    StudentDao中的deleteStudentById方法:

    public boolean deleteStudentById(String id) {
            boolean b = false;
            for (int i = 0; i < students.length; i++) {
                Student student = students[i];
                if (student.getId().equals(id)) {
                    students[i] = null;
                    b = true;
                    break;
                }
            }
            return b;
        }
    

    测试效果:


    image.png

    8、修改学生代码实现

    这里我就不一一去分析了,大家可以参照前面的三个对它每个类里面的修改方法做功能分析,我在这里就直接上代码了。
    StudentController中的updateStudentById方法:

    public void updateStudentById() {
            Scanner sc1 = new Scanner(System.in);
            String id;
    
            System.out.println("请输入需要修改的学生id:");
            id = sc1.next();
            boolean flag = studentservice.isExits(id);
            if (!flag) {
                System.out.println("未找到该名学生!");
                return;
            }
            System.out.println("请输入学生姓名:");
            String name = sc1.next();
            System.out.println("请输入学生年龄:");
            String age = sc1.next();
            System.out.println("请输入学生生日:");
            String birthday = sc1.next();
            //2、将学生信息封装为学生对象传递给StudentService
            Student stu = new Student(id, name, age, birthday);
            //3、将学生对象传递给StudentService中的addStudent方法
    
            boolean result = studentservice.updateStudentById(stu,id);
            //4、接收方法的boolean类型返回值,根据结果在控制台打印添加成功\添加失败
            if (result) {
                System.out.println("修改成功");
            } else {
                System.out.println("修改失败");
            }
        }
    

    StudentService中的updateStudentById方法:

    public boolean updateStudentById(Student stu, String id) {
            return studentdao.updateStudentById(stu,id);
        }
    

    StudentDao中的updateStudentById方法:

    public boolean updateStudentById(Student stu, String id) {
            boolean b1 = false;
            for (int i = 0; i < students.length; i++) {
                Student student = students[i];
                if (student.getId().equals(id)) {
                    students[i] = stu;
                    b1 = true;
                    break;
                }
            }
            return b1;
        }
    

    最后上一个测试截图:


    image.png

    总结:其实开发这样一个简单的学生管理系统非常简单,甚至可能觉得我把这个过程弄得非常复杂,很多人会觉得没必要这样,我想说的是,这么简单的系统很多人都能做,我只是想通过这个简单的demo来温习一下Java中的分类分包思想,什么包下的类需要做什么事,每个包下面的类分工合作完成整个工程,这才是我想要传达给大家的,这在开发中对降低代码耦合度有很好的作用,我们在开发中也应该时刻把这种原则放在第一位,否则写出来的代码会变得杂乱无章,甚至自己维护都非常费力,更别提代码迭代了。
    就这样吧,有问题请评论去留言,会第一时间改正。。

    相关文章

      网友评论

          本文标题:Java-----基于面向对象开发学生管理系统

          本文链接:https://www.haomeiwen.com/subject/araefrtx.html