Java--图书管理系统(简易版)

目录

目录

前言

🔔1.library包

1.1 Book类

1.2 BookList类

🔔2.user包

2.1User类(父类)

2.2Admin(管理员)

2.3 NormalUser(普通用户)

🔔3.Operation包

🕐3.1 IOperation接口

🕑3.2ListOperation(查看操作)

🕒3.3AddOperation(增加操作)

🕓3.4BorrowOperation(借书操作)

🕔3.5ReturnOperation(还书操作)

🕕3.6DelOperation(删除操作)

🕖3.7FindOperation(查找操作) 

🕗3.8ExitOperation(退出操作)

🔔4.Main类

🔔5.效果展示


(ps:✨在本篇文章中我们介绍了图书管理系统📖,但是功能很少,所以在下一篇文章中,我又增加了几个功能:大家可以点击链接移步到下一篇文章(无讲解的)

https://blog.csdn.net/2401_84024092/article/details/147874135?fromshare=blogdetail&sharetype=blogdetail&sharerId=147874135&sharerefer=PC&sharesource=2401_84024092&sharefrom=from_link

前言

🌈本篇文章会实现一个控制台版本的“图书管理系统”,涉及到 JavaSE中的继承,多态,抽象类,接口。(代码部分附有详细的讲解✨)

在这个系统中:

1.能够表示多本图书的信息📘

2.提供两种用户:管理员普通用户

3.普通用户可以查看书籍列表查找图书📖,借书,还书

4.管理员可以查看书籍列表,查找图书📖,新增图书,删除图书

整体框架如下:🎉

程序目录如下:🎉

🔔1.library包

1.1 Book类

👉每本书📕都被定义为一个类,其中包含书名、作者、类型、价格和借阅状态等属性。这些属性均被设置为private访问权限,并通过getter和setter方法进行访问和修改。在类的构造方法中,我们会对这些属性进行初始化,其中借阅状态默认设置为未借出(false)。

package library;
//一本书
public class Book {//现实世界的书private String name;private String author;private String type;private double price;private boolean isBorrowed;public Book(String name, String author, String type, double price){this.name=name;this.author=author;this.type=type;this.price=price;this.isBorrowed=false;}//alt+ins自动生成
//get,set方法可以随时更改属性,但是构造方法只能初始化一次public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public String getType() {return type;}public void setType(String type) {this.type = type;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}public boolean isBorrowed() {return isBorrowed;}public void setBorrowed(boolean borrowed) {isBorrowed = borrowed;}@Overridepublic String toString() {return "Book{" +"name='" + name + '\'' +", author='" + author + '\'' +", type='" + type + '\'' +", price=" + price +", isBorrowed=" + (isBorrowed?"已借出":"未借出") +'}';}
}

1.2 BookList类

👉用来管理多个书籍对象

首先定义一个Book类类型的数组books,共分配1024个空间

✨注意:我们约定好,所有有效的书籍,都是从0开始连续递增排列的,以便可以通过size来描述有效书籍数目

package library;public class BookList {private Book[] books=new Book[1024];//此数组中每个类型都是Book类类型//长度不方便灵活调整,预先创造大空间//把booklist想象为一个书架,书架总共有1024个位置,不能修改大小,所以设置为private//长度不方便灵活调整,预先创造大空间private int size =0;//有效元素public BookList(){books[0]=new Book("西游记","吴承恩","古典小说",100);//books[0]中存放的是一组实例对象books[1]=new Book("红楼梦","曹雪芹","古典小说",90);books[2]=new Book("高等数学","高斯","数学",40);books[3]=new Book("Java入门","詹姆斯高斯林","计算机",70);books[4]=new Book("红楼梦","曹雪芹","古典小说",90);size=5;}public Book getBook(int index) {//得到序号为index的书籍return books[index];//不会越界,因为此时还没满}public void setBook(int index,Book book) {books[index] = book;}//将序号index处设置为××书public int getSize() {return size;//有效书籍数量}public void setSize(int size) {this.size = size;//设置有效书籍数量}
}

🔔2.user包

两种用户:普通用户🙎‍♀️+管理员👩‍🏫

✨注意:普通用户与管理员的操作即存在重复的部分,也存在不同的部分,因此可以通过继承,把相同的部分通过父类(User)提取出来

2.1User类(父类)

将抽象菜单方法(menu)定义在父类中,供子类重写实现,并通过 IOperation[] 数组存储管理员和用户可执行的功能操作。

package library.user;import library.BookList;
import library.IOperation;public abstract class User {//不同 的用户不同的操作protected String name;//各个子类都有的内容,直接放在父类中//protected子类可以直接获取到,不必再去用getter setterprotected IOperation[] operations;//当前这个类能进行那些操作,就往这个数组里添加对应的对象public User(String name){this.name=name;}public abstract int menu();//不知道父类的菜单(父类就没有菜单),我知道的只有管理员和用户的菜单// 所以使用abstract,子类再进行重写//为了避免父类被不小心创建出实例,所以要抽象(因为不能出现“父类菜单”)public void work(int choice, BookList bookList){//3.进入到父类的work方法if(choice<0||choice>=operations.length){System.out.println("输入的选项非法");return;}operations[choice].work(bookList);//4.调用我选择的方法里面的work方法,就能用此方法对booklist进行操作了}
}

2.2Admin(管理员)

🔔管理员应继承父类User,通过重写父类的 menu 方法,实现了自定义菜单功能,用户可通过输入选择进入相应功能模块。在子类构造函数中,首先调用父类构造方法完成名称初始化,随后对用户操作进行配置(包括退出,查看,查找、新增、删除的功能)。

注意:IOperation[]中的顺序已经和菜单中的选项对应了

package library.user;import library.IOperation;
import library.Operation.*;import java.util.Scanner;public class Admin extends User{//private IOperation[] operations;//存放管理员的方法,这是什么类型呢,接口类型public Admin(String name) {super(name);operations=new IOperation[]{new ExitOperation(),new ListOperation(),new FindOperation(),new AddOperation(),new DelOperation(),};}@Overridepublic int menu() {System.out.println("==============================");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.println("===============================");System.out.println("请输入您的操作:");Scanner scanner=new Scanner(System.in);int choice = scanner.nextInt();return choice;}
}

2.3 NormalUser(普通用户)

🔔普通用户应继承父类User,通过重写父类的 menu 方法,实现了自定义菜单功能,用户可通过输入选择进入相应功能模块。在子类构造函数中,首先调用父类构造方法完成名称初始化,随后对用户操作进行配置(包括退出,查看,查找、借书、还书的功能)。

package library.user;import library.Operation.IOperation;
import library.Operation.*;import java.util.Scanner;public class NormalUser extends User {//private IOperation[] operations;public NormalUser(String name) {super(name);//对所要的方法进行初始化operations = new IOperation[]{//普通用户进行的操作new ExitOperation(),//这是一个数组,此处下标为0new ListOperation(),new FindOperation(),new BorrowOperation(),new ReturnOperation(),};}@Overridepublic int menu() {//打印菜单System.out.println("==============================");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.println("===============================");System.out.println("请输入您的操作:");Scanner scanner=new Scanner(System.in);int choice = scanner.nextInt();return choice;}
}

🔔3.Operation包

👓此包中包括所有需要进行的操作类

🔔🔔🔔看到这里我们发现,书籍和用户并没有建立起联系,那么如何将BookList与用户实现“交互”呢?

通过IOperation接口把用户和书给关联起来

🕐3.1 IOperation接口

增加这个接口后,所有的操作类都要实现自IOperation接口,并重写其中的work方法,在每个操作类中的work方法的具体实现各不相同

✨注意:这里有人可能会问:如果不设置接口,只在每个类中都写上work方法,将参数BookList作为参数传递进去不就可以进行书籍与操作的联系吗,为什么还要设置接口呢

原因:简单来说就是限制代码的灵活性

解释:理论上是可行的,但是不加接口的话,无法保证所有的类都提供了work方法,也没法保证work方法的参数都是相同的。而加上后就能强制统一,方便后续的调用,否则如果大家提供的方法各不相同,就会显得很乱。

package library.Operation;import library.BookList;public interface IOperation {//也可以使用抽象类,但是我这个接口我只想保存一些方法,并没有什么实例属性要继承的//并且不能多继承//而User中的类是抽象性,因为我们需要继承name的属性void work(BookList bookList);
}

🕑3.2ListOperation(查看操作)

✨在每一次循环中都会创建一次book对象

✨接着调用booklist中的getBook方法获取到第i本书

当i为0时,创建的对象就是

Book book = new Book("西游记","吴承恩","古典小说",100);

最后实现打印操作,当打印book时,会自动调用Book类中的toString方法(打印格式可以自行调整)

package library.Operation;import library.Book;
import library.BookList;public class ListOperation implements IOperation {@Overridepublic void work(BookList bookList) {System.out.println("查看书籍列表");for(int i=0;i<bookList.getSize();i++){Book book = bookList.getBook(i);//拿到第i本书System.out.println("["+i+"]"+book);}}
}

🕒3.3AddOperation(增加操作)

让用户输入新的书籍📕的信息,然后把这个新的书放到BookList

这本新书存放到数组的最后一个位置上,在BookList中已经存在N本书了(size),这些书对应的下标[0,N-1],新的图书📕就放到N的位置即可,在相应位置传入书后,有效元素size也要加一

package library.Operation;import library.Book;
import library.BookList;import java.util.Scanner;public class AddOperation implements IOperation {@Overridepublic void work(BookList bookList) {System.out.println("新增图书");Scanner scanner=new Scanner(System.in);System.out.println("请输入书名:");String name = scanner.next();System.out.println("请输入作者:");String author =scanner.next();System.out.println("请输入价格");double price = scanner.nextDouble();System.out.println("请输入类别");String type=scanner.next();Book book =new Book(name,author,type,price);int size=bookList.getSize();bookList.setBook(size,book);//传入book就相当于传入引用的空间bookList.setSize(size+1);//不能忘了修改sizeSystem.out.println("新增图书完成!");}
}

🕓3.4BorrowOperation(借书操作)

✨在借书操作时,要注意判断是否被借出

package library.Operation;import library.Book;
import library.BookList;import java.util.Scanner;public class BorrowOperation implements IOperation {@Overridepublic void work(BookList bookList) {System.out.println("借书");Scanner scanner=new Scanner(System.in);System.out.println("请输入要借阅的图书编号:");int id= scanner.nextInt();if(id<0||id>=bookList.getSize()){System.out.println("输入错误");return;}Book book=bookList.getBook(id);//获取第id本书对象if(book.isBorrowed()){//先判断一下是否被借出System.out.println("该书已经被借出了");//如果真就被借出了return;}book.setBorrowed(true);//没借出我就可以借了System.out.println("借书成功!");}
}

🕔3.5ReturnOperation(还书操作)

✨在借书操作时,也要注意判断书是否已经被归还了

package library.Operation;import library.Book;
import library.BookList;import java.util.Scanner;public class ReturnOperation implements IOperation {@Overridepublic void work(BookList bookList) {System.out.println("还书");Scanner scanner=new Scanner(System.in);System.out.println("请输入要归还的图书编号:");int id= scanner.nextInt();if(id<0||id>=bookList.getSize()){System.out.println("输入错误");return;}Book book=bookList.getBook(id);if(!book.isBorrowed()){//先判断一下是否被借出falseSystem.out.println("该书没借出,不能归还");//如果没被借出了,就不能换return;}book.setBorrowed(false);System.out.println("还书成功!");}
}

🕕3.6DelOperation(删除操作)

✨在进行删除操作时,如果是最后一本书📕,直接将有效元素size-1即可

如果是中间位置元素,可以把最后一本书📕放在待删除元素的位置上,然后再size-1即可。

package library.Operation;import library.Book;
import library.BookList;import java.util.Scanner;public class DelOperation implements IOperation {@Overridepublic void work(BookList bookList) {System.out.println("删除书籍");Scanner scanner=new Scanner(System.in);System.out.println("请输入要删除书籍的序号:");int index=scanner.nextInt();if(index<0||index>=bookList.getSize()) {System.out.println("序号超出范围");return;}if(index == bookList.getSize()-1){bookList.setSize(bookList.getSize()-1);//如果是最后一本书,直接将有效元素设置为size-1即可}else{//如果删除中间元素,就可以把最后一个元素,复制到待删除元素的位置上,然后size-1即可Book lastBook = bookList.getBook(bookList.getSize()-1);//先获取到最后一本书bookList.setBook(index,lastBook);bookList.setSize(bookList.getSize()-1);}System.out.println("删除书籍完成!");}
}

🕖3.7FindOperation(查找操作) 

✨查找操作只需验证输入内容与书籍列表中的条目是否一致。

package library.Operation;import library.Book;
import library.BookList;import java.util.Scanner;public class FindOperation implements IOperation {@Overridepublic void work(BookList bookList) {System.out.println("查找操作");Scanner scanner=new Scanner(System.in);System.out.println("请输入查找的书名");String name =scanner.next();for(int i=0;i<bookList.getSize();i++){Book book = bookList.getBook(i);if(book.getName().equals(name)){//比较字符串用这个System.out.println(book);}}System.out.println("查找完毕");}
}

🕗3.8ExitOperation(退出操作)

package library.Operation;import library.BookList;public class ExitOperation implements IOperation {@Overridepublic void work(BookList bookList) {System.out.println("goodbye!");System.exit(0);//退出整个程序}
}

🔔4.Main类

✨在主类中根据用户输入跳转到具体的用户

package library;import library.user.NormalUser;
import library.user.User;
import library.user.Admin;
import java.util.Scanner;
public class Main {private static User login(){System.out.println("请输入您的姓名:");Scanner scanner =new Scanner(System.in);String name = scanner.next();System.out.println("请输入您的角色(1.普通用户2.管理员)");int role = scanner.nextInt();if (role==1){return new NormalUser(name);}else if(role==2){return new Admin(name);}else{System.out.println("输入的角色有误");return null;}}public static void main(String[] args) {//书记管理library.BookList booklist=new BookList();//管理员和普通用户让用户选择User user = login();//User user=new NormalUser(name)//User user=new Admin(name)//向上转型while(true){int choice = user.menu();//多态user.work(choice,booklist);//将选择的菜单与书籍列表传入,假如是查找,普通用户}}
}

🔔5.效果展示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/82575.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入浅出:Spring Boot 中 RestTemplate 的完整使用指南

在分布式系统开发中&#xff0c;服务间通信是常见需求。作为 Spring 框架的重要组件&#xff0c;RestTemplate 为开发者提供了简洁优雅的 HTTP 客户端解决方案。本文将从零开始讲解 RestTemplate 的核心用法&#xff0c;并附赠真实地图 API 对接案例。 一、环境准备 在 Spring…

大数据处理利器:Hadoop 入门指南

一、Hadoop 是什么&#xff1f;—— 分布式计算的基石 在大数据时代&#xff0c;处理海量数据需要强大的技术支撑&#xff0c;Hadoop 应运而生。Apache Hadoop 是一个开源的分布式计算框架&#xff0c;致力于为大规模数据集提供可靠、可扩展的分布式处理能力。其核心设计理念是…

685SJBH计量管理系统

摘 要 计量&#xff0c;在我国已有五千年的历史。计量的发展与社会进步联系在一起&#xff0c;它是人类文明的重要组成部分。它的发展经历了古典阶段、经典阶段和现代阶段。而企业的计量管理是对测量数据、测量过程和测量设备的管理。 本系统通过分析现有计量系统的业务逻辑…

从0到1构建前端监控系统:错误捕获、性能采集、用户体验全链路追踪实战指南SDK实现

目录 前言为什么要做前端监控前端监控目标稳定性用户体验业务 前端监控流程常见埋点方案代码埋点可视化埋点无痕埋点 创建项目第一步、创建monitor文件&#xff0c;cmd进入文件进行npm init -y 项目初始化第二步、创建src/index.js和src/index.html文件第三步、创建webpack.con…

前端浏览器判断设备类型的方法

前端浏览器判断设备类型的方法 在前端开发中&#xff0c;判断设备类型&#xff08;如手机、平板、桌面电脑&#xff09;有多种方法&#xff0c;以下是常用的几种方式&#xff1a; 1. 使用 User Agent 检测 通过 navigator.userAgent 获取用户代理字符串进行判断&#xff1a;…

MNIST 手写数字分类

转自我的个人博客: https://shar-pen.github.io/2025/05/04/torch-distributed-series/1.MNIST/ 基础的单卡训练 本笔记本演示了训练一个卷积神经网络&#xff08;CNN&#xff09;来对 MNIST 数据集中的手写数字进行分类的过程。工作流程包括&#xff1a; 数据准备&#xff…

数据库中的 Segment、Extent、Page、Row 详解

在关系型数据库的底层存储架构中&#xff0c;数据并不是随意写入磁盘&#xff0c;而是按照一定的结构分层管理的。理解这些存储单位对于优化数据库性能、理解 SQL 执行过程以及排查性能问题都具有重要意义。 我将从宏观到微观&#xff0c;依次介绍数据库存储中的四个核心概念&…

DAMA车轮图

DAMA车轮图是国际数据管理协会&#xff08;DAMA International&#xff09;提出的数据管理知识体系&#xff08;DMBOK&#xff09;的图形化表示&#xff0c;它以车轮&#xff08;同心圆&#xff09;的形式展示了数据管理的核心领域及其相互关系。以下是基于用户提供的关键词对D…

《QDebug 2025年4月》

一、Qt Widgets 问题交流 1. 二、Qt Quick 问题交流 1.QML单例动态创建的对象&#xff0c;访问外部id提示undefined 先定义一个窗口组件&#xff0c;打印外部的id&#xff1a; // MyWindow.qml import QtQuick 2.15 import QtQuick.Window 2.15Window {id: controlwidth: …

JS | 正则 · 常用正则表达式速查表

以下是前端开发中常用的正则表达式速查表&#xff0c;包含验证规则、用途说明与示例&#xff1a; &#x1f4cc; 常用正则表达式速查表 名称正则表达式描述 / 用途示例手机号/^1[3-9]\d{9}$/中国大陆手机号13812345678 ✅座机号/^0\d{2,3}-?\d{7,8}$/固定电话010-12345678 ✅…

系统思考:个人与团队成长

四年前&#xff0c;我交付的系统思考项目&#xff0c;今天学员的反馈依然深深触动了我。 我常常感叹&#xff0c;系统思考不仅仅是一场培训&#xff0c;更像是一场持续的“修炼”。在这条修炼之路上&#xff0c;最珍贵的&#xff0c;便是有志同道合的伙伴们一路同行&#xff0…

写屏障和读屏障的区别是什么?

写屏障&#xff08;Write Barrier&#xff09;与读屏障&#xff08;Read Barrier&#xff09;的区别 在计算机科学中&#xff0c;写屏障和读屏障是两种关键的内存同步机制&#xff0c;主要用于解决并发编程中的可见性、有序性问题&#xff0c;或在垃圾回收&#xff08;GC&…

ssh -T git@github.com 测试失败解决方案:修改hosts文件

问题描述 通过SSH方式测试&#xff0c;使用该方法测试连接可能会遇到连接超时、端口占用的情况&#xff0c;原因是因为DNS配置及其解析的问题 ssh -T gitgithub.com我们可以详细看看建立 ssh 连接的过程中发生了什么&#xff0c;可以使用 ssh -v命令&#xff0c;-v表示 verbo…

大疆无人机搭载树莓派进行目标旋转检测

环境部署 首先是环境创建&#xff0c;创建虚拟环境&#xff0c;名字叫 pengxiang python -m venv pengxiang随后激活环境 source pengxiang/bin/activate接下来便是依赖包安装过程了: pip install onnxruntime #推理框架 pip install fastapi uvicorn[standard] #网络请求…

00 Ansible简介和安装

1. Ansible概述与基本概念 1.1. 什么是Ansible&#xff1f; Ansible 是一款用 Python 编写的开源 IT 自动化工具&#xff0c;主要用于配置管理、软件部署及高级工作流编排。它能够简化应用程序部署、系统更新等操作&#xff0c;并且支持自动化管理大规模的计算机系统。Ansibl…

Linxu实验五——NFS服务器

一.NFS服务器介绍 NFS服务器&#xff08;Network File System&#xff09;是一种基于网络的分布式文件系统协议&#xff0c;允许不同操作系统的主机通过网络共享文件和目录3。其核心作用在于实现跨平台的资源透明访问&#xff0c;例如在Linux和Unix系统之间共享静态数据&#…

『 测试 』测试基础

文章目录 1. 调试与测试的区别2. 开发过程中的需求3. 开发模型3.1 软件的生命周期3.2 瀑布模型3.2.1 瀑布模型的特点/缺点 3.3 螺旋模型3.3.1 螺旋模型的特点/缺点 3.4 增量模型与迭代模型3.5 敏捷模型3.5.1 Scrum模型3.5.2 敏捷模型中的测试 4 测试模型4.1 V模型4.2 W模型(双V…

红外遥控键

红外 本章节旨在让用户自定义红外遥控功能&#xff0c;需要有板载红外接收的板卡。 12.1. 获取红外遥控键值 由于不同遥控器厂家定义的按键键值不一样&#xff0c;所以配置不通用&#xff0c;需要获取实际按键对应的键值。 1 2 3 4 5 6 #设置输出等级 echo 7 4 1 7> /pr…

同一个虚拟环境中conda和pip安装的文件存储位置解析

文章目录 存储位置的基本区别conda安装的包pip安装的包 看似相同实则不同的机制实际路径示例这种差异带来的问题如何检查包安装来源最佳实践建议 总结 存储位置的基本区别 conda安装的包 存储在Anaconda(或Miniconda)目录下的pkgs和envs子目录中&#xff1a; ~/anaconda3/en…