Java实现图书管理系统:OOP设计与完整源码解析

Ada
Ada
发布时间:2026-10-16 | 4人浏览过
原创

本教程通过Java手写一个简单的图书管理系统,详细讲解如何利用面向对象(OOP)特性进行系统设计。内容涵盖用户权限分类、书籍数据存储及核心功能的接口实现,帮助开发者掌握Java基础语法在实际工程中的综合应用。

在学习完Java基本语法后,通过一个小项目来串联知识点是非常有效的学习方式。我们将开发一个基于控制台的图书管理系统,核心目标是实现管理员与普通用户的不同权限操作,以及图书的增删改查功能。

系统分析与架构设计

在编码之前,我们需要明确系统中的核心对象及其交互关系:

  1. 数据模型层:需要 Book(书本信息)和 BookShelf(书架容器)来管理图书资源。
  2. 用户管理层:系统存在两种角色——普通用户和超级管理员,他们拥有不同的菜单权限。
  3. 操作逻辑层:所有具体的业务操作(如借书、还书、删除)独立封装为模块,通过接口统一调用。

为了保持代码整洁,我们按照职责划分包结构:book 包负责数据,user 包负责用户类,operate 包负责具体功能实现。

第一步骤:实现数据模型 (book)

首先定义图书实体类 Book。该类用于封装书的属性,遵循封装原则,成员变量设为私有并提供 Getter/Setter 方法。为了支持初始化,添加一个构造方法。

package book;
public class Book {
    private String name;
    private String author;
    private String type;
    private int price;
    // 借阅状态:true表示被借出,false表示在馆
    private boolean borrow;

    public Book() {}

    public Book(String name, String author, String type, int price) {
        this.name = name;
        this.author = author;
        this.type = type;
        this.price = price;
        this.borrow = false;
    }
    // 省略标准的 getter 和 setter 方法...
}

接着,我们需要一个容器来存放这些书。虽然实际项目中会使用数据库,但在此项目中我们使用 Book 类型的数组。创建一个 BookShelf 类作为书架管理容器:

package book;
public class BookShelf {
    // 预定义最大容量为1000本书
    private Book[] books = new Book[1000];
    // 记录当前书架上的有效图书数量
    private int count = 1;

    public BookShelf() {
        // 默认初始化一本书
        books[0] = new Book("呐喊", "鲁迅", "小说集", 30);
    }

    // 设置指定位置的图书
    public void setBooks(int pos, Book book) {
        books[pos] = book;
    }

    // 获取指定下标的图书对象
    public Book pos(int i) {
        return books[i];
    }

    // 获取当前图书总数
    public int getCount() {
        return count;
    }

    // 更新图书总数
    public void setCount(int count) {
        this.count = count;
    }
}

第二步骤:构建用户体系与多态 (user)

系统中包含“管理员”和“普通用户”两类用户。由于两者登录方式相似但后续功能不同,我们可以利用 Java 的多态特性:

  1. 定义一个抽象基类 User,包含用户名和菜单展示方法。
  2. 创建子类 AdminUser 和 NormalUser 分别继承自 User。

父类抽象代码片段:

public abstract class User {
    private String name;
    public IOperate[] ioperate; // 绑定该用户可执行的操作列表

    public User(String name) {
        this.name = name;
    }

    public abstract int menu(); // 返回选择的指令ID

    // 根据用户选择的指令执行对应操作
    public void chooseOperate(int choice, BookShelf bookShelf) {
        // 安全检查:防止越界访问
        if (choice >= 0 && choice < ioperate.length) {
            ioperate[choice].work(bookShelf);
        } else {
            System.out.println("输入错误");
        }
    }
}

子类实现示例(以管理员为例,重点在于 ioperate 数组的赋值):

public class AdminUser extends User {
    public AdminUser(String name) {
        super(name);
        // 管理员拥有的操作:退出、查找、新增、删除、显示
        // 索引0通常预留或对应退出,需与实际菜单显示顺序保持一致
        this.ioperate = new IOperate[] {
                null,       // index 0: placeholder for Exit or other
                new FindBook(),
                new AddBook(),
                new DelBook(),
                new DisplayBook()
        };
    }

    @Override
    public int menu() {
        System.out.println("欢迎" + name + "管理员!");
        System.out.println("1. 查找图书");
        System.out.println("2. 新增图书");
        System.out.println("3. 删除图书");
        System.out.println("4. 显示图书");
        System.out.println("0. 退出系统");
        System.out.print("请输入你的选择: ");
        Scanner scanner = new Scanner(System.in);
        return scanner.nextInt();
    }
}

普通用户 NormalUser 的实现类似,但其 ioperate 数组中应包含借书、还书等操作类。

第三步骤:实现功能操作 (operate)

为了实现业务逻辑的扩展性,我们定义一个操作接口 IOperate。所有的具体操作(如新增、删除)都实现这个接口。

package operate;
import book.BookShelf;
public interface IOperate {
    void work(BookShelf bookShelf);
}

以“新增图书”功能 AddBook 为例,演示如何接收用户输入并更新书架:

package operate;
import book.Book;
import book.BookShelf;
import java.util.Scanner;

public class AddBook implements IOperate {
    @Override
    public void work(BookShelf bookShelf) {
        System.out.println("请输入图书名字:");
        Scanner scanner = new Scanner(System.in);
        String name = scanner.nextLine();
        System.out.println("请输入作者:");
        String author = scanner.nextLine();
        System.out.println("请输入类型:");
        String type = scanner.nextLine();
        System.out.println("请输入价格:");
        int price = scanner.nextInt();

        Book book = new Book(name, author, type, price);
        int currentCount = bookShelf.getCount();
        
        // 存入数组,并增加计数
        bookShelf.setBooks(currentCount, book);
        bookShelf.setCount(currentCount + 1);
        
        System.out.println("新增成功!");
    }
}

对于其他操作(如 DelBook, BorrowBook),同样遵循此模式:获取用户输入 → 遍历 BookShelf 查找目标 → 修改对象状态 → 保存结果。

第四步骤:主程序入口与逻辑流转

在主程序中,我们通过循环模拟系统的持续运行。每次循环询问用户名及身份,实例化对应的 User 对象,然后进入操作循环。

import user.User;
import user.AdminUser;
import user.NormalUser;
import book.BookShelf;

public class Main {
    public static void main(String[] args) {
        BookShelf shelf = new BookShelf();
        Scanner input = new Scanner(System.in);
        
        while(true) {
            System.out.print("请输入姓名: ");
            String name = input.nextLine();
            System.out.println("请选择身份: 1. 管理员  2. 普通用户");
            int role = input.nextInt();
            
            User currentUser = null;
            if (role == 1) {
                currentUser = new AdminUser(name);
            } else {
                currentUser = new NormalUser(name);
            }

            // 进入用户专属操作循环
            while(true) {
                int choice = currentUser.menu();
                if (choice == 0) break;
                currentUser.chooseOperate(choice, shelf);
            }
        }
    }
}

注意事项与优化建议

  • 内存泄漏问题:在编写退出功能时,建议遍历数组将引用置为 null,虽然 JVM 会在进程结束后自动回收,但在大型应用中这是良好的习惯。
  • toString 重写:直接打印对象会输出内存地址。建议在 Book 类中重写 toString() 方法,以便在列表中清晰展示图书信息。
  • 数据校验:当前代码未对输入价格或书名做合法性检查,实际开发中需加入正则判断或非空校验。

以上就是Java实现图书管理系统的设计思路与代码细节,更多关于Java面向对象实战的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表