Java基础(7)图书管理系统
目录
1.前言
2.正文
2.1思路
2.2Book包
2.3people包
2.4operation包
2.5主函数
3.小结
1.前言
哈喽大家好吖,今天来给前面Java基础的学习来一个基础的实战,做一个简单的图书管理系统,这里边综合利用了我们之前学习到的类和对象,继承与多态以及抽象类和接口等许多重要的概念以及知识,事不宜迟,让我们开始吧。
2.正文
2.1思路
在正式开始图书管理系统的代码完成前,我们需要先对一系列所需要创建的对象,各个对象之间的关系,如何实现这种关系,都要有一个提前的规划,下面我通过PlantUML生成了图书管理系统的基础框架,我据图一一解释。

在图书管理系统里面,会参与各种行为的对象都有哪些呢?有书本,借阅者,管理员,具体的借阅功能等,所以我们一共有四个包,分别为:
- Book包
operation包
people
主函数所在包
我们把各个模块把它分成各个包来进行封装,是代码的条理性更好。
2.2Book包
在Book包中,我们创建了俩个对象,一个是book对象,另一个书用于存放书的bookshelf对象,具体实现如下:
package Book;public class Book {private String bookName;private String writer;private String classification;private Boolean borrow;public Book(String bookName, String writer, String classification, Boolean borrow) {this.bookName = bookName;this.writer = writer;this.classification = classification;this.borrow = borrow;}public String getBookName() {return bookName;}public void setBookName(String bookName) {this.bookName = bookName;}public String getWriter() {return writer;}public void setWriter(String writer) {this.writer = writer;}public String getClassification() {return classification;}public void setClassification(String classification) {this.classification = classification;}public Boolean getBorrow() {return borrow;}public void setBorrow(Boolean borrow) {this.borrow = borrow;}
}
因为成员的访问权限我们设置为private,所以我们需要各种getter和setter方法来调用成员变量,其中getter和setter方法是可以通过系统快速生成的,即按住alt+insert可以快速实现该方法。
下面是Bookshelf对象:
package Book;public class bookShelf {private Book[] books = new Book[10];private int bookNum = 0;public bookShelf() {this.books[0] = new Book("三国演义","罗贯中","历史演义",null);this.books[1] = new Book("三体","刘慈欣","科幻小说",null);this.books[2] = new Book("西游记","吴承恩","小说",null);this.bookNum = 3;}public Book getBooks(int pos) {return books[pos];}public void setBooks(Book book,int pos) {this.books[pos] = book;}public int getBookNum() {return bookNum;}public void setBookNum(int bookNum) {this.bookNum = bookNum;}
}
我们在bookshelf的构造方法中提前初始化里三个对象,即可以理解为图书馆中原本就存放的书。创建一个bookNum变量用于记录当前所存放的图书数量。
2.3people包
在people包中我们通过继承来实现,首先创建了一个person抽象类用于抽取管理员和借阅者的共同属性以及方法,再分别实现子类Admin与normalUser。
person类:
package People;import operation.*;
import Book.*;public abstract class Person {public String name;public Operation[] iOperations;public Person(String name) {this.name = name;}public abstract int menu();public void finishOPerations(int choice,bookShelf bookShelf) {iOperations[choice].work(bookShelf);}
}
共同属性姓名不必多说,还额外创建了一个功能数组,另外创建一个菜单方法用于打印各自的菜单,最后还有finishOPeration方法,通过这个功能数组即可实现输入菜单对应选项进入对应功能的操作。
Admin类:
package People;import operation.*;import java.util.Scanner;public class Admin extends Person {public Admin(String name) {super(name);this.iOperations = new Operation[]{new edit(),new showBook(),new findBook(),new addBook(),new delBook()};}@Overridepublic int menu() {System.out.println("*******************");System.out.println("**欢迎来到管理员菜单**");System.out.println("******0.退出系统*****");System.out.println("******1.显示图书*****");System.out.println("******2.寻找图书*****");System.out.println("******3.增加图书*****");System.out.println("******4.减少图书*****");System.out.println("*******************");Scanner scanner = new Scanner(System.in);int choice = scanner.nextInt();return choice;}}
在这个构造方法中需要对功能数组中添加功能方法,下文同样。
normalUser类:
package People;import operation.*;import java.util.Scanner;public class normalUser extends Person {@Overridepublic int menu() {System.out.println("*******************");System.out.println("***欢迎来到用户菜单***");System.out.println("******0.退出系统*****");System.out.println("******1.显示图书*****");System.out.println("******2.寻找图书*****");System.out.println("******3.借阅图书*****");System.out.println("******4.归还图书*****");System.out.println("*******************");Scanner scanner = new Scanner(System.in);int choice = scanner.nextInt();return choice;}public normalUser(String name) {super(name);this.iOperations = new Operation[]{new edit(),new showBook(),new findBook(),new borrowBook(),new returnBook()};}}
2.4operation包
在这个包里面,我们尝试把各种人物的行为全都各个创建成对象来进行分别实现,这里我们采用了接口,即在这个包里接了这个接口的其他对象,都需要将接口中的方法重写,来达到方法都得到实现的目的。
首先是接口:
package operation;import Book.bookShelf;public interface Operation {public void work(bookShelf bookShelf);
}
接口中的方法不需要具体实现。
接下来就是各种需要实现的对象与对象之间的逻辑了,如借阅图书,归还图书,查询图书,退出系统等,我一一进行讲解:
findBook类:
package operation;import Book.Book;
import Book.bookShelf;
import java.util.Scanner;//找书先要判断是否有书,若有则借,若无则直接返回
public class findBook implements Operation{public void work(bookShelf bookShelf){Scanner scanner = new Scanner(System.in);System.out.println("查找图书");String name = scanner.nextLine();for(int i = 0;i < bookShelf.getBookNum();i++){if(name.equals(bookShelf.getBooks(i).getBookName())){System.out.println("找到了《" + name + "》书");return;}}System.out.println("未找到"+ "《"+ name + "》");}
}
通过遍历来实现,若遍历到有此书则打印找到了并返回,若能走完遍历则未找到。
showBook类:
package operation;import Book.bookShelf;public class showBook implements Operation{public void work(bookShelf bookShelf) {System.out.println("显示图书");//遍历书架for (int i = 0; i < bookShelf.getBookNum(); i++) {System.out.println(bookShelf.getBooks(i));}}}
这个遍历打印即可,没什么特殊。
addBook类:
//新增图书,先判断该书是否存在,再实例化一个书对象添加进bookshelf,并将bookNum增加package operation;import Book.Book;
import Book.bookShelf;
import java.util.Scanner;public class addBook implements Operation {@Overridepublic void work(bookShelf bookShelf) {Scanner scanner = new Scanner(System.in);System.out.println("请输入添加的图书名字");String name = scanner.nextLine();System.out.println("请输入添加的图书作者名字");String writer = scanner.nextLine();System.out.println("请输入添加的图书分类");String classfication = scanner.nextLine();//遍历判断是否有相同书for(int i = 0;i < bookShelf.getBookNum();i++){if(name.equals(bookShelf.getBooks(i).getBookName())){System.out.println("书库里已有该书");return;}}//新增图书bookShelf.setBooks(new Book(name,writer,classfication,false), bookShelf.getBookNum());bookShelf.setBookNum(bookShelf.getBookNum() + 1);//新增图书加1System.out.println("书《" + name +"》已添加成功");}
}
新增图书是属于Admin对象的类方法,先输入要添加的书的各个成员变量的信息,再遍历寻找有无相同书,若没有则添加。
delBook类:
//删除一本书,现需要查找是否有该书,删书即使后一个覆盖前一个即可package operation;import Book.Book;
import Book.bookShelf;
import java.util.Scanner;public class delBook implements Operation{@Overridepublic void work(bookShelf bookShelf) {Scanner scanner = new Scanner(System.in);System.out.println("请输入你需要删除的书");String name = scanner.nextLine();for(int i = 0;i < bookShelf.getBookNum();i++){if(name.equals(bookShelf.getBooks(i).getBookName())){for(int j = i;j < bookShelf.getBookNum() - 1;j++){bookShelf.setBooks(bookShelf.getBooks(j + 1),j);}bookShelf.setBookNum(bookShelf.getBookNum() - 1);System.out.println("该书已删除完毕");return;}}System.out.println("不存在该书");}
}
也是遍历寻找输入的书,若找到删除的书,则将后面的书一一往前覆盖即可实现删除功能,最后不要忘了bookNum要进行减一操作。
borrowBook类:
package operation;import Book.Book;
import Book.bookShelf;
import java.util.Scanner;public class borrowBook implements Operation{@Overridepublic void work(bookShelf bookShelf) {Scanner scanner = new Scanner(System.in);System.out.println("请输入要借阅书的名字");String name = scanner.nextLine();for(int i = 0;i < bookShelf.getBookNum();i++){if(name.equals(bookShelf.getBooks(i).getBookName())){bookShelf.getBooks(i).setBorrow(true);//设置借阅状态System.out.println("书《" + name +"》借阅成功");return;}}System.out.println("不存在该书,借阅失败");}
}
还是先遍历找书,若有则改变图书的借阅状态,若无则借阅失败。
returnBook类:
package operation;import Book.bookShelf;import java.util.Scanner;public class returnBook implements Operation{@Overridepublic void work(bookShelf bookShelf) {Scanner scanner = new Scanner(System.in);System.out.println("请输入要归还书的名字");String name = scanner.nextLine();for(int i = 0;i < bookShelf.getBookNum();i++){if(name.equals(bookShelf.getBooks(i).getBookName())){bookShelf.getBooks(i).setBorrow(false);//设置借阅状态System.out.println("书《" + name +"》归还成功");return;}}System.out.println("不存在该书,归还失败");}
}
和借书操作如出一辙,唯一的区别就是状态改变的true与false不同。
edit类:
package operation;import Book.bookShelf;public class edit implements Operation{@Overridepublic void work(bookShelf bookShelf) {for(int i = 0;i < bookShelf.getBookNum();i++){bookShelf.setBooks(null,i);}bookShelf.setBookNum(0);System.exit(0);}
}
实现退出功能,先将储存的图书删除,将bookNum清零,最后退出系统。
2.5主函数
在主函数中同样,我们把登陆(即选择自己是管理员还是借阅者身份的选择)的login功能也通过单独的类方法来进行实现。
Login类:
package System;import People.Admin;
import People.Person;
import People.normalUser;import java.util.Scanner;public class Login{public Person loginIn(){System.out.println("*欢迎来到图书管理系统**");Scanner scanner = new Scanner(System.in);System.out.println("请输入你的名字");String name = scanner.nextLine();System.out.println("*******************");System.out.println("******1.管理员******");System.out.println("******2.普通用户****");System.out.println("请输入你的身份");if(scanner.nextInt() == 1){return new Admin(name);}else{return new normalUser(name);}}
}
最后就是主函数,这个时候主函数就会比较整洁明了,记得要分别实例化书架bookShelf对象以及Login登陆对象了。
package System;import Book.*;
import People.*;public class system {public static void main(String[] args) {bookShelf bookShelf = new bookShelf();Login login = new Login();Person person = login.loginIn();while(true){int choice = person.menu();person.finishOPerations(choice,bookShelf);}}}
这样我们图书管理系统就完成了!
3.小结
今天的图书管理系统的分享到这里就结束了,喜欢的小伙伴不要忘了点一手关注再走哦,欢迎大家在评论区多多交流哦。
相关文章:
Java基础(7)图书管理系统
目录 1.前言 2.正文 2.1思路 2.2Book包 2.3people包 2.4operation包 2.5主函数 3.小结 1.前言 哈喽大家好吖,今天来给前面Java基础的学习来一个基础的实战,做一个简单的图书管理系统,这里边综合利用了我们之前学习到的类和对象&…...
使用 Spring Boot 实现图片上传
目录 一、前言 二、项目准备 2.1、创建SpringBoot项目 2.2、项目结构 2.3、配置文件 2.4、创建控制器 2.5、创建服务 2.6创建前端界面 2.7、静态资源 三、运行项目 四、测试上传功能 总结 一、前言 在现代 web 开发中,图片上传功能是一个…...
深度解析跨境支付之产品架构
跨境支付企业有能力开放更多的底层能力接口给到外界合作伙伴。其中包括购汇及申报、结汇及申报、换汇(包含汇率查询和外汇兑换、远期锁汇等功能)、境外本地下单、查询、退款、外汇跨境收款、海外代发、VA账户开户及余额查询、VCC发卡及查询等能力。 在这…...
Linux下的线程同步与死锁避免
文章目录 死锁的四个必要条件破坏死锁条件的方法破坏互斥条件使用读写锁(pthread_rwlock_t) 破坏持有并等待条件一次性申请所有资源 破坏不可剥夺条件使用超时锁定机制可重入锁(递归锁) 破坏循环等待条件统一锁顺序 在 Linux 下进…...
【Python爬虫实战】Selenium自动化网页操作入门指南
#1024程序员节|征文# 🌈个人主页:易辰君-CSDN博客 🔥 系列专栏:https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、准备工作 (一)安装 Selenium 库 ࿰…...
mono源码交叉编译 linux arm arm64全过程
初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…...
矩阵的可解性:关于Ax=b的研究
上一篇文章讲解了如何求解 A x 0 Ax0 Ax0,得到 A A A的零空间。 类似的,我们今天学习的是如何求解 A x b Axb Axb,并以此加强你对线性代数中,代数与空间的理解。 同样的,我们举与上一次一样的例子,矩阵 …...
10.22.2024刷华为OD C题型(三)--for循环例子
脚踝动了手术,现在宾馆恢复,伤筋动骨一百天还真不是说笑的,继续努力吧。 文章目录 靠谱的车灰度图恢复灰度图恢复 -- for循环使用例子 靠谱的车 https://www.nowcoder.com/discuss/564514429228834816 这个题目思路不难,就是要自…...
QT:MaintenanceTool 模块安装工具
QT的MaintenanceTool 工具对已安装的 Qt 进行卸载、修复等其他操作时提示At least one valid and enabled repository required for this action to succeed 解决方式:在设置中添加一个临时的仓库 https://mirrors.tuna.tsinghua.edu.cn/qt/online/qtsdkrepositor…...
同标签实现监听LocalStorage
使用 React 生命周期函数 useEffect来监听和处理 LocalStorage 的变化 import React, { useEffect } from react;const LocalStorageListener () > {useEffect(() > {// 注册监听器const handleStorageChange (event) > {if (event.key myKey) {console.log(注册…...
JAVA高性能缓存项目
版本一 代码实现 import java.util.HashMap; import java.util.concurrent.TimeUnit;public class CacheExample01 {private final static HashMap<String, Integer> cache new HashMap<>();public static Integer check(String userId) throws InterruptedExce…...
智慧农业大数据平台:智汇田园,数驭未来
智慧农业大数据平台 计讯物联智慧农业大数据平台是一个集管理数字化、作业自动化、生产智能化、产品绿色化、环境信息化、服务现代化于一体的多功能监管系统。它通过与硬件产品的搭配使用,实现对农业生产全过程的实时监测、精准控制和科学管理。该平台集成了多个数…...
Go语言基础教程:可变参数函数
Go 语言允许函数接收可变数量的参数,这种特性对于处理数量不确定的参数特别有用。在本教程中,我们将通过示例代码讲解如何定义和使用 Go 的可变参数函数。 package mainimport "fmt"// 定义一个可变参数函数 sum,接收任意数量的整…...
高并发场景下解决并发数据不一致
简单的场景: 全量数据更新的情况下, 不在乎同一秒的请求都必须要成功, 只留下最新的更新请求数据 方案常用的是 1、数据库增加时间戳标识实现的乐观锁, 请求参数从源头带上微秒或者毫秒时间戳数据库存储, 然后在更新SQL语句上比较 (数据库的时间 < 参数传递的时间) 例如: A…...
OpenAI GPT-o1实现方案记录与梳理
本篇文章用于记录从各处收集到的o1复现方案的推测以及介绍 目录 Journey Learning - 上海交通大学NYUMBZUAIGAIRCore IdeaKey QuestionsKey TechnologiesTrainingInference A Tutorial on LLM Reasoning: Relevant methods behind ChatGPT o1 - UCL汪军教授Core Idea先导自回归…...
Excel:vba实现生成随机数
Sub 生成随机数字()Dim randomNumber As IntegerDim minValue As IntegerDim maxValue As Integer 设置随机数的范围(假入班级里面有43个学生,学号是从1→43)minValue 1maxValue 43 生成随机数(在1到43之间生成随机数)randomNumber Application.WorksheetFunctio…...
Python | Leetcode Python题解之第506题相对名次
题目: 题解: class Solution:desc ("Gold Medal", "Silver Medal", "Bronze Medal")def findRelativeRanks(self, score: List[int]) -> List[str]:ans [""] * len(score)arr sorted(enumerate(score), …...
安全见闻(6)
声明:学习视频来自b站up主 泷羽sec,如涉及侵权马上删除文章 感谢泷羽sec 团队的教学 视频地址:安全见闻(6)_哔哩哔哩_bilibili 学无止境,开拓自己的眼界才能走的更远 本文主要讲解通讯协议涉及的安全问题。…...
Promise、async、await 、异步生成器的错误处理方案
1、Promise.all 的错误处理 Promise.all 方法接受一个 Promise 数组,并返回所有解析 Promise 的结果数组: const promise1 Promise.resolve("one"); const promise2 Promise.resolve("two");Promise.all([promise1, promise2]).…...
腾讯云:数智教育专场-学习笔记
15点13分2024年10月21日(短短5天的时间,自己的成长速度更加惊人)-开始进行“降本增效”学习模式,根据小米手环对于自己的行为模式分析(不断地寻找数据之间的关联性),每天高效记忆时间࿰…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...
通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...
