于鸿硕面向对象设计大作业02

面向对象设计大作业02

网安2411 于鸿硕 202421336018

一、改造思路

1.MVC模式

MVC模式 即Model-View-Controller(模型-视图-控制器)模式,通过分三种实现模块进行;对于本项目,设计MVC模式如下

graph TD M[Model]-->|数据存储|S[Student.java]-->StudentController.java M-->|业务方法|StudentManagementSystem.java-->StudentController.java View-->|控制台视图|ConsoleView.java-->StudentController.java View-->|用户图形视图|GUIView.java-->StudentController.java StudentController.java-->Controller

总体上,通过StudentController对Model和View进行调动,实现程序运行

2.GUI实现

使用JTable表格的方式展示学生数据,实现数据直接可视化

3.双界面支持

程序启动时选择使用的界面类型,两种界面指向共同的控制器和模型以精简代码和减小时空复杂度,两种界面数据和功能互通


二、实现方式

1.Model

model模块Student和StudentManagementSystem两个类沿用既有类,不作修改

2.View

StudentView.java(视图接口类)

用该类承接Main方法引入的视图,并初始化视图方法

package code;

import java.util.List;

public interface StudentView {
    void setController(StudentController controller);
    void updateStudentList(List<Student> students);
    void showSearchResults(List<Student> results);
    void showMessage(String message);
    void start();
}
ConsoleView.java(控制台视图)

该类可直接继承原系统中Main文件的代码,通过Override实现该类方法

package code;

import java.util.List;
import java.util.Scanner;

public class ConsoleView implements StudentView {
    private StudentController controller;
    private Scanner scanner;

    public ConsoleView() {
        scanner = new Scanner(System.in);
    }

    @Override
    public void setController(StudentController controller) {
        this.controller = controller;
    }

    @Override
    public void updateStudentList(List<Student> students) {
        if (students.isEmpty()) {
            System.out.println("系统中没有学生数据!");
            return;
        }
        System.out.println("学生列表:");
        for (Student student : students) {
            System.out.println(student);
        }
    }

    @Override
    public void showSearchResults(List<Student> results) {
        if (results.isEmpty()) {
            System.out.println("没有找到匹配的学生!");
        } else {
            System.out.println("搜索结果:");
            for (Student student : results) {
                System.out.println(student);
            }
        }
    }

    @Override
    public void showMessage(String message) {
        System.out.println(message);
    }

    @Override
    public void start() {
        boolean running = true;
        while (running) {
            System.out.println("\n===== 学生管理系统 =====");
            System.out.println("1. 添加学生");
            System.out.println("2. 移除学生");
            System.out.println("3. 按姓名搜索");
            System.out.println("4. 按专业搜索");
            System.out.println("5. 按GPA搜索");
            System.out.println("6. 显示所有学生");
            System.out.println("7. 退出");
            System.out.print("请选择操作: ");

            int choice = scanner.nextInt();
            scanner.nextLine(); //  consume newline

            switch (choice) {
                case 1:
                    addStudentForm();
                    break;
                case 2:
                    removeStudentForm();
                    break;
                case 3:
                    searchByNameForm();
                    break;
                case 4:
                    searchByMajorForm();
                    break;
                case 5:
                    searchByGpaForm();
                    break;
                case 6:
                    controller.showAllStudents();
                    break;
                case 7:
                    running = false;
                    System.out.println("系统已退出");
                    break;
                default:
                    System.out.println("无效的选择,请重试");
            }
        }
        scanner.close();
    }

    private void addStudentForm() {
        System.out.print("请输入学生姓名: ");
        String name = scanner.nextLine();
        System.out.print("请输入学生年龄: ");
        int age = scanner.nextInt();
        scanner.nextLine();
        System.out.print("请输入学生性别: ");
        String gender = scanner.nextLine();
        System.out.print("请输入学生ID: ");
        String id = scanner.nextLine();
        System.out.print("请输入学生专业: ");
        String major = scanner.nextLine();
        System.out.print("请输入学生GPA: ");
        double gpa = scanner.nextDouble();

        controller.addStudent(name, age, gender, id, major, gpa);
        showMessage("学生添加成功!");
    }

    private void removeStudentForm() {
        System.out.print("请输入要移除的学生ID: ");
        String id = scanner.nextLine();
        boolean removed = controller.removeStudent(id);
        if (removed) {
            showMessage("学生移除成功!");
        } else {
            showMessage("未找到该学生!");
        }
    }

    private void searchByNameForm() {
        System.out.print("请输入要搜索的学生姓名: ");
        String name = scanner.nextLine();
        controller.searchByName(name);
    }

    private void searchByMajorForm() {
        System.out.print("请输入要搜索的专业: ");
        String major = scanner.nextLine();
        controller.searchByMajor(major);
    }

    private void searchByGpaForm() {
        System.out.print("请输入要搜索的GPA: ");
        double gpa = scanner.nextDouble();
        controller.searchByGpa(gpa);
    }
}
GUIView.java(图形视图)

通过Swing GUI展示用户界面,通过JButton、JField创建交互,新建或Override方法对接Controller

// GUIView.java (GUI视图)
package code;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;

public class GUIView extends JFrame implements StudentView {
    private StudentController controller;
    private DefaultTableModel tableModel;
    private JTable table;
    private JTextField nameField, ageField, genderField, idField, majorField, gpaField;
    private JTextField searchField;

    public GUIView() {
        setTitle("学生管理系统");
        setSize(800, 600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        initComponents();
        setLocationRelativeTo(null);
    }

    private void initComponents() {
        // 表格设置
        String[] columns = {"姓名", "年龄", "性别", "ID", "专业", "GPA"};
        tableModel = new DefaultTableModel(columns, 0);
        table = new JTable(tableModel);
        add(new JScrollPane(table), BorderLayout.CENTER);

        // 控制面板
        JPanel controlPanel = new JPanel(new GridLayout(3, 1));

        // 添加学生面板
        JPanel addPanel = new JPanel(new FlowLayout());
        addPanel.setBorder(BorderFactory.createTitledBorder("添加学生"));

        addPanel.add(new JLabel("姓名:"));
        nameField = new JTextField(5);
        addPanel.add(nameField);

        addPanel.add(new JLabel("年龄:"));
        ageField = new JTextField(3);
        addPanel.add(ageField);

        addPanel.add(new JLabel("性别:"));
        genderField = new JTextField(3);
        addPanel.add(genderField);

        addPanel.add(new JLabel("ID:"));
        idField = new JTextField(5);
        addPanel.add(idField);

        addPanel.add(new JLabel("专业:"));
        majorField = new JTextField(8);
        addPanel.add(majorField);

        addPanel.add(new JLabel("GPA:"));
        gpaField = new JTextField(3);
        addPanel.add(gpaField);

        JButton addButton = new JButton("添加");
        addButton.addActionListener(e -> addStudentAction());
        addPanel.add(addButton);

        controlPanel.add(addPanel);

        // 搜索面板
        JPanel searchPanel = new JPanel(new FlowLayout());
        searchPanel.setBorder(BorderFactory.createTitledBorder("搜索学生"));

        searchField = new JTextField(10);
        searchPanel.add(searchField);

        JButton nameSearchButton = new JButton("按姓名搜索");
        nameSearchButton.addActionListener(e -> searchByNameAction());
        searchPanel.add(nameSearchButton);

        JButton majorSearchButton = new JButton("按专业搜索");
        majorSearchButton.addActionListener(e -> searchByMajorAction());
        searchPanel.add(majorSearchButton);

        JButton gpaSearchButton = new JButton("按GPA搜索");
        gpaSearchButton.addActionListener(e -> searchByGpaAction());
        searchPanel.add(gpaSearchButton);

        controlPanel.add(searchPanel);

        // 操作面板
        JPanel actionPanel = new JPanel(new FlowLayout());

        JButton removeButton = new JButton("移除选中学生");
        removeButton.addActionListener(e -> removeStudentAction());
        actionPanel.add(removeButton);

        JButton showAllButton = new JButton("显示所有学生");
        showAllButton.addActionListener(e -> controller.showAllStudents());
        actionPanel.add(showAllButton);

        JButton exitButton = new JButton("退出");
        exitButton.addActionListener(e -> System.exit(0));
        actionPanel.add(exitButton);

        controlPanel.add(actionPanel);

        add(controlPanel, BorderLayout.NORTH);
    }

    private void addStudentAction() {
        try {
            String name = nameField.getText();
            int age = Integer.parseInt(ageField.getText());
            String gender = genderField.getText();
            String id = idField.getText();
            String major = majorField.getText();
            double gpa = Double.parseDouble(gpaField.getText());

            controller.addStudent(name, age, gender, id, major, gpa);

            // 清空输入框
            nameField.setText("");
            ageField.setText("");
            genderField.setText("");
            idField.setText("");
            majorField.setText("");
            gpaField.setText("");

            showMessage("学生添加成功");
        } catch (NumberFormatException ex) {
            showMessage("输入格式错误,请检查年龄和GPA是否为数字");
        }
    }

    private void removeStudentAction() {
        int selectedRow = table.getSelectedRow();
        if (selectedRow >= 0) {
            String id = (String) tableModel.getValueAt(selectedRow, 3);
            boolean removed = controller.removeStudent(id);
            if (removed) {
                showMessage("学生移除成功");
            } else {
                showMessage("学生移除失败");
            }
        } else {
            showMessage("请先选择要移除的学生");
        }
    }

    private void searchByNameAction() {
        String name = searchField.getText();
        controller.searchByName(name);
    }

    private void searchByMajorAction() {
        String major = searchField.getText();
        controller.searchByMajor(major);
    }

    private void searchByGpaAction() {
        try {
            double gpa = Double.parseDouble(searchField.getText());
            controller.searchByGpa(gpa);
        } catch (NumberFormatException ex) {
            showMessage("GPA必须是数字");
        }
    }

    @Override
    public void setController(StudentController controller) {
        this.controller = controller;
    }

    @Override
    public void updateStudentList(List<Student> students) {
        tableModel.setRowCount(0); // 清空表格
        for (Student student : students) {
            Object[] row = {
                    student.getName(),
                    student.getAge(),
                    student.getGender(),
                    student.getId(),
                    student.getMajor(),
                    student.getGpa()
            };
            tableModel.addRow(row);
        }
    }

    @Override
    public void showSearchResults(List<Student> results) {
        updateStudentList(results);
        showMessage("找到 " + results.size() + " 个匹配结果");
    }

    @Override
    public void showMessage(String message) {
        JOptionPane.showMessageDialog(this, message);
    }

    @Override
    public void start() {
        setVisible(true);
    }
}

3.Controller

StudentController.java(控制器)

作为视图和模型的中继器,实现Student的getter、setter方法

package code;

import java.util.List;

public class StudentController {
    private StudentManagementSystem model;
    private StudentView view;

    public StudentController(StudentManagementSystem model, StudentView view) {
        this.model = model;
        this.view = view;
        this.view.setController(this);
    }

    // 添加学生
    public void addStudent(String name, int age, String gender, String id, String major, double gpa) {
        Student student = new Student(name, age, gender, id, major, gpa);
        model.addStudent(student);
        view.updateStudentList(model.getStudents());
    }

    // 移除学生
    public boolean removeStudent(String id) {
        Student student = model.getStudentById(id);
        if (student != null) {
            model.removeStudent(student);
            view.updateStudentList(model.getStudents());
            return true;
        }
        return false;
    }

    // 按姓名搜索
    public void searchByName(String name) {
        List<Student> results = model.searchByName(name);
        view.showSearchResults(results);
    }

    // 按专业搜索
    public void searchByMajor(String major) {
        List<Student> results = model.searchByMajor(major);
        view.showSearchResults(results);
    }

    // 按GPA搜索
    public void searchByGpa(double gpa) {
        List<Student> results = model.searchByGpa(gpa);
        view.showSearchResults(results);
    }

    // 显示所有学生
    public void showAllStudents() {
        view.updateStudentList(model.getStudents());
    }
}

4.Main.java

对Main方法进行重新设计,进入程序后先映入界面选择,而后通过View类进入对应的界面,再而创建控制器关联模型和视图,最后启动程序

package code;

import javax.swing.*;

public class Main {
	public static void main(String[] args) {		
		StudentManagementSystem model = new StudentManagementSystem();

		String[] options = {"控制台界面", "GUI界面"};
		int choice = JOptionPane.showOptionDialog(
				null,
				"请选择界面类型",
				"学生管理系统",
				JOptionPane.DEFAULT_OPTION,
				JOptionPane.INFORMATION_MESSAGE,
				null,
				options,
				options[0]
		);

		StudentView view;
		if (choice == 1) {
			view = new GUIView();
		} else {
			view = new ConsoleView();
		}

		StudentController controller = new StudentController(model, view);
		view.start();
	}
}

三、运行截图

img

图1 界面分流

img

图2 控制台视图菜单栏

img

图3.1 GUI视图首页

img

图3.2 GUI添加学生

img

图3.3 GUI按专业搜索

img

图3.4 GUI按GPA搜索

img

图3.5 GUI显示所有学生

![image-20251031153438521](D:\Personal Official Files\GIthub Workstation\image-20251031153438521.png)

图3.6 GUI选中移除学生


四、总结说明

本次实验通过学习MVC模式、JTable展示模式概念和方法,将各个类框架及其要求输出给豆包AI,后得到完整代码。

代码中最大的难理解点是多态多接口情况下,容易被多个类和方法绕晕,不知道这段代码指给谁,只懂得代码起什么作用,不懂得其背后的逻辑;解决的好方法是建立精细的思维导图,精细到每个类的每个方法,在结构可视化后代码底层逻辑变得清晰好理解

代码一大复杂度出现在Swing GUI专属的类处,由于图形界面需要多条指令来实现单个方法,所以代码会堆积复杂,串联程度很高,对于程序员来说维护成本和难度也很高

综上,我发现MVC和GUI模式结合的这种方法好处体现在框架明确,在全局上连通性好、对某个方法修改不需要到每一个类里一个一个重新写,同时具有接入更多功能和更多模块的良好适应性,但是对于较小型的程序,例如这次改造的学生管理系统,会造成代码过多过繁杂,反向增加维护成本,瑜不掩瑕。

所以我认为,MVC模式适用于较大型、未来扩充可能大的系统,GUI图形适用于需要商品化、专业化、美观化的程序产品;如果是不需要完成以上需求的程序,例如较小型的、仅供程序员和技术人员监控、更改的专业小应用程序,使用传统的控制台模式更方便便捷。

在得出上述结论以外,我学习了GUI的语法和MVC模式思想,基本掌握了调用AI改造自己程序的方法。

posted @ 2025-10-31 15:47  KinthYu  阅读(5)  评论(0)    收藏  举报