当前位置: 首页 > news >正文

【项目】图书管理系统

目录

前言:

项目要求:

知识储备:

代码实现:

Main:

Books包:

Book:

BookList:

Operate包:

Operate:

addOperate:

deleteOperate:

exitOperate:

findOperate:

showOperate:

Persion包:

User: 

Admin:

Reader:


前言:

随着javaSE的学习深入,我们已经明白了什么是类和对象,学会了继承和多态,抽象类和接口,那么我们就可以利用以上几个知识点来完成一个小项目图书管理系统来检验一下我们学习的成果,我们主要完成其框架和一些基本点(起到复习作用,不是为了业务)。

项目要求:

实现一个图书管理系统,有两个用户,普通用户和管理员,两个用户的业务不一样,实现其业务,书有书名,作者,价格,书的类型,是否被借出。

普通用户:0.退出系统 1.查找图书 2.借阅图书 3.归还图书 

管理员用户:0.推出系统 1.查找图书 2.新增图书 3.删除图书 4.显示图书

知识储备:

java基本语法,类和对象,继承和多态,抽象类和接口。

具体效果如下动图所示。

代码实现:

为了培养优良的代码风格,我们将各个模块区分开来,故我们需要创建3个包(有关包如果不太了解的话可以看看封装和包)分别是Books和Operate,Person,功能和其的英文名一样,最后用一个Main类把他们串在一起。

Main:

动态绑定:也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体 调用那个类的方法.

先创建一个书架BookList(具体代码后续给出,重要的是思路),User是Admin(管理员)和Reader(普通用户)的父类,使用User来接受这是因为在代码编译的时候程序并不知道是普通用户还是管理员,只有在我们输入后才确定下来(动态绑定),发生向上转型。用一个while来实现循环输入,因为两个用户的菜单不一样,故我们可以在User中定义一个抽象方法,在两个具体子类中实现,放回的k即为我们的选择操作。user.doOperate(books,k)是我觉的这个项目最精彩的地方,这里先简单理解为调用user,对books进行第k个操作,具体我会在Operate部分详细解释。

import Person.*;
import java.util.Scanner;
import Books.*;public class Main {private static User Logon(){Scanner scanner = new Scanner(System.in);System.out.print("请输入你的姓名: ");String name = scanner.next();System.out.print("请输入你的身份: 1: 管理员   2: 普通用户-> : ");int index = scanner.nextInt();if(index == 1){return new Admin(name);}else if(index == 2){return new Reader(name);}else{System.out.println("输入错误");System.exit(0);return null;}}public static void main(String[] args) {BookList books = new BookList();User user = Logon();//动态绑定while(true){int k = user.menu();user.doOperate(books,k);}}
}

Books包:

在Books包中存储这两个类Book类中存储书的一般属性,BookList就是书架。

Book:

为了更加安全和代码的封装性我们把变量用private修饰,在下面用set和get方法来进行修改。构造方法不用构造isBorrowed因为没有初始化的话java默认为false。

package Books;/*** 书的基本参数*/
public class Book {private String name;private String author;private int price;private String type;//书的类型private boolean isBorrowed;//是否被借出  默认值是falsepublic Book(String name, String author, int price, String type) {this.name = name;this.author = author;this.price = price;this.type = type;}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 int getPrice() {return price;}public void setPrice(int price) {this.price = price;}public String getType() {return type;}public void setType(String type) {this.type = type;}public boolean isBorrowed() {return isBorrowed;}public void setBorrowed(boolean borrowed) {isBorrowed = borrowed;}@Overridepublic String toString() {return "Book{" +"name='" + name + '\'' +", author='" + author + '\'' +", price=" + price +", type='" + type + '\'' +", isBorrowed=" + ((isBorrowed == false) ? "未借出" : "已借阅") +//不确定加括号'}';}
}

要想使用println来直接打印Book的话必须要重写toString方法,下图是println的源码,在valueof中有obj.toStirng的参数,我们基本类型的toString系统已经实现,Book为我们自己定义的一个类所以要自己实现一下。

BookList:

书架上不仅要能放书还要能记录书本的个数,一开始直接初始化3本书方便我们后续调试。

package Books;/*** 书架*/
public class BookList {private Book[] books;//能放书private int BookSize;//记录书本的个数public BookList() {books = new Book[10];this.books[0] = new Book("三国演义","罗贯中",10,"小说");this.books[1] = new Book("西游记","吴承恩",9,"小说");this.books[2] = new Book("红楼梦","曹雪芹",19,"小说");this.BookSize = 3;}public Book[] getBooks() {return books;}public void setBooks(int index,Book books) {this.books[index] = books;}public int getBookSize() {return BookSize;}public void setBookSize(int bookSize) {BookSize = bookSize;}
}

Operate包:

Operate:

这里不是包是一个接口,因为每个操作都只要实现work功能故我们定义一个接口来规范我们的代码,方便后面进行向上转型,work前面可以不用加public abstract系统默认会给你加上

package Operate;
import Books.*;public interface Operate {void work(BookList books);
}

addOperate:

由于本项目难点并不在业务的实现,主要集中在一个框架,故下面的借阅图书和归还图书就由读者自行实现(很简单的)。

package Operate;
import Books.*;
import java.util.*;public class addOperate implements Operate {@Overridepublic void work(BookList books) {Scanner scanner = new Scanner(System.in);System.out.println("请输入书名: ");String name = scanner.next();System.out.println("请输入作者: ");String author = scanner.next();System.out.println("请输入价格: ");int price = scanner.nextInt();System.out.println("请输入书的类型: ");String type = scanner.next();Book book = new Book(name,author,price,type);int usedSize = books.getBookSize();books.setBooks(usedSize,book);books.setBookSize(usedSize + 1);System.out.println("添加成功");System.out.println();}
}

deleteOperate:

package Operate;
import Books.*;
import java.util.Scanner;
public class deleteOperate implements Operate {public void work(BookList books){Scanner scanner = new Scanner(System.in);System.out.print("请输入你要删除书的书名: ");String name = scanner.next();Book[] book = books.getBooks();//浅拷贝int bookSize = books.getBookSize();for(int i = 0;i < bookSize;i++){if(name.equals(book[i].getName())){for(int j = i;j < bookSize - 1;j++){book[j] = book[j + 1];}book[bookSize - 1] = null;System.out.println("删除成功");System.out.println();books.setBookSize(bookSize - 1);return;}}System.out.println("该图书不存在,删除失败");System.out.println();}
}

exitOperate:

package Operate;
import Books.BookList;
public class exitOperate implements Operate{@Overridepublic void work(BookList books) {System.out.println("退出系统");System.exit(0);}
}

 

findOperate:

package Operate;
import Books.BookList;
import Books.Book;
import java.util.Scanner;
public class findOperate implements Operate {@Overridepublic void work(BookList books) {Scanner scanner = new Scanner(System.in);System.out.print("请输入你要查找书的名字: ");String name = scanner.next();Book[] book = books.getBooks();int usedSize = books.getBookSize();for(int i = 0;i < usedSize;i++){if(name.equals(book[i].getName())){System.out.println("找到了,信息如下: ");System.out.println(book[i]);System.out.println();return;}}System.out.println("该图书不存在");System.out.println();}
}

showOperate:

package Operate;
import Books.BookList;
import Books.Book;
public class showOperate implements Operate{@Overridepublic void work(BookList books) {int usedSize = books.getBookSize();Book[] book = books.getBooks();for(int i = 0;i < usedSize;i++){System.out.println(book[i]);}System.out.println();}
}

Persion包:

User是Admin和Reader的父类。

User: 

用一个Operate[]的数组来存储我们上面实现的方法类,因为两个用户对于的方法是不一样的故使用Operate放在User中那个用户需要哪个方法直接new一个方法类在该数组中(向上转型),要调用的时候通过下标访问即可。因为菜单要根据具体是那个用户来具体实现故要把它抽象就可以不用实现,故我们要把User定义成抽象类。

package Person;
import Operate.*;
import Books.*;
public abstract class User {protected String name;protected Operate[] operates;public void doOperate(BookList books,int choice){operates[choice].work(books);}public User(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public abstract int menu();//菜单
}

Admin:

利用super来调用父类的构造方法,在operates中需要什么方法类就直接new上那个方法类,需要注意的是下标的映射关系。继承一个抽象类其子类必须要重写抽象方法。

package Person;
import Operate.*;
import java.util.Scanner;
public class Admin extends User{public Admin(String name){super(name);this.operates = new Operate[]{new exitOperate(),new findOperate(),new addOperate(),new deleteOperate(),new showOperate()};}@Overridepublic int menu() {Scanner scanner = new Scanner(System.in);System.out.println("***********管理员***********");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.print("请输入你的操作: ");int index = scanner.nextInt();return index;}
}

Reader:

和上面的Admin一样这里就不再赘述。

package Person;
import java.util.Scanner;
import Operate.*;
public class Reader extends User{public Reader(String name){super(name);this.operates = new Operate[]{new exitOperate(),new findOperate(),new borrowOperate(),new returnOperate()};}@Overridepublic int menu() {Scanner scanner = new Scanner(System.in);System.out.println("***********读者***********");System.out.println("1.查找图书");System.out.println("2.借阅图书");System.out.println("3.归还图书");System.out.println("0.推出系统");System.out.println("**************************");System.out.print("请输入你的操作: ");int index = scanner.nextInt();return index;}
}

总结:大家最好自己实现一遍,实现的时候最好要明白自己在做什么,可以看看最后的结果来捋捋思路,可以看到我们使用到了接口,抽象类,包和继承的相关知识,只有在你使用他们的时候才会明白那里缺了。

结语:

其实写博客不仅仅是为了教大家,同时这也有利于我巩固自己的知识点,和一个学习的总结,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进,如果大家有所收获的话还请不要吝啬你们的点赞收藏和关注,这可以激励我写出更加优秀的文章。

相关文章:

【项目】图书管理系统

目录 前言&#xff1a; 项目要求&#xff1a; 知识储备&#xff1a; 代码实现&#xff1a; Main&#xff1a; Books包&#xff1a; Book&#xff1a; BookList&#xff1a; Operate包&#xff1a; Operate: addOperate: deleteOperate: exitOperate: findOperate:…...

华为OD机试 - 疫情扩散时间计算 - 矩阵(Java 2024 C卷 200分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷C卷&am…...

[数据集][图像分类]棉花叶子病害分类数据集2293张4类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;2293 分类类别数&#xff1a;4 类别名称:["diseased_cotton_leaf"…...

《辐射4》是一款什么样的游戏 怎样在mac电脑上玩到《辐射4》辐射4攻略 辐射4开局加点 怎么在Mac电脑玩Steam游戏

辐射4&#xff08;Fallout 4&#xff09;是由Bethesda开发的一款动作角色扮演类游戏&#xff0c;为《辐射》系列游戏作品的第四代&#xff0c;于2015年11月10日发行。游戏叙述了主角一家在核爆当天&#xff08;2077年10月23日&#xff09;&#xff0c;被Vault-Tec&#xff08;避…...

视频推拉流EasyDSS平台直播通道重连无法转推的原因排查与解决

视频推拉流EasyDSS视频直播点播平台&#xff0c;集视频直播、点播、转码、管理、录像、检索、时移回看等功能于一体&#xff0c;可提供音视频采集、视频推拉流、播放H.265编码视频、存储、分发等视频能力服务。 用户使用EasyDSS平台对直播通道进行转推&#xff0c;发现只要关闭…...

Javaweb之SpringBootWeb案例之自动配置案例的自定义starter测试的详细解析

3.2.4.3 自定义starter测试 阿里云OSS的starter我们刚才已经定义好了&#xff0c;接下来我们就来做一个测试。 今天的课程资料当中&#xff0c;提供了一个自定义starter的测试工程。我们直接打开文件夹&#xff0c;里面有一个测试工程。测试工程就是springboot-autoconfigurat…...

java包的相关概念

包&#xff1a;有效地管理类的一个机制。 包名的目的&#xff1a;通过隶属不同的包有效的区分不同源文件中名字相同的类 包语句 声明&#xff1a;通过关键字 package声明包语句。 位置&#xff1a;源文件中的第一条语句。 作用&#xff1a;为该源文件中声明的类指定包名。 …...

window搭建本地mongo数据库并导入数据

1 window下载mongo数据库 官网&#xff1a;www.mongodb.com 选择 Products > Community Edition 就能进入社区版 在这里下载 windows 版对应的安装包 注意&#xff1a;6.0.1 版本的 MongoDB 配置环境变量有问题&#xff0c;并且我不知道怎么解决&#xff0c;如果想要避免出…...

如何为Android车载应用开发通知?

如何为Android车载应用开发通知&#xff1f;在开发车载应用的通知时&#xff0c;开发者需要考虑到驾驶安全&#xff0c;确保通知不会分散驾驶员的注意力。这通常意味着通知应该是非侵入性的&#xff0c;或者在不影响驾驶的情况下提供信息。开发者可以使用Android的通知API来创建…...

centos上部署k8s

环境准备 四台Linux服务器 主机名 IP 角色 k8s-master-94 192.168.0.94 master k8s-node1-95 192.168.0.95 node1 k8s-node2-96 192.168.0.96 node2 habor 192.168.0.77 镜像仓库 三台机器均执行以下命令&#xff1a; 查看centos版本 [rootlocalhost Work]# cat /…...

网络安全: Kali Linux 进行 MSFvenom 程序利用

目录 一、实验 1.环境 2. Kali Linux 进行 MSFvenom 程序利用 3. 创建计划任务自动运行 MSFvenom 程序 二、问题 1.在线加密解密 2.MSF 运行失败 3.MobaXterm 连接Ubuntu 失败 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 系统版本IP备注Kali Linux20…...

浅显易懂C语言指针!!!(三)

文章目录 Pointers as function arguments - call by reference//函数传值vs传引用 Pointers as function arguments - call by reference//函数传值vs传引用 #include<stdio.h> void Increment(int a){//increment 增加 a a 1;//&#xff1b;函数中的是形式参数 形参…...

01 LM 算法及 Cpp 实现

文章目录 01 LM 算法及 Cpp 实现1.1 应用1.2 阻尼法推导1.3 Cpp 算法实现 01 LM 算法及 Cpp 实现 1.1 应用 LM 算法用于解决非线性最小二乘问题 min ⁡ x F ( x ) 1 2 ∥ f ( x ) ∥ 2 2 (1) \min _x F(x)\frac{1}{2}\|f(\boldsymbol{x})\|_2^2 \tag{1} xmin​F(x)21​∥f(x…...

【网络安全架构】互联网正对中国社会、经济、文化等各个领域产生巨大影响‘

摘 要&#xff1a; 中国互联网近年来飞速发展&#xff0c;普及率达到38.4%。已稳居世界第一网民大国的地位。互联网正对社会、经济、文化等各个领域产生巨大影响。2011年12月21日“泄密门”事件&#xff0c;再次敲响网络安全的警钟。网络攻击和入侵都是根据网络模型不同层次的特…...

【笔记】Android ServiceStateTracker 网络状态变化逻辑及SPN更新影响

业务简介 在网络状态变化的时候&#xff08;数据或WiFi&#xff09;&#xff0c;会更新SPN。 基于Android U的代码分析。 分类&#xff1a;SPN Data_Dic-的博客-CSDN博客 功能逻辑 状态说明 飞行模式下注册上WFC的话&#xff0c;注册状态MD上报 regState: NOT_REG_MT_NOT…...

2PC和3PC的区别是什么

2PC提交协议是什么 二阶段提交是指&#xff0c;在计算机网络一级数据库领域内&#xff0c;为了使基于分布式系统的架构下的所有节点在进行事务提交时保持一致性而设计的一种算法。在分布式系统中&#xff0c;每个节点虽然可以知晓自己操作的成功和失败&#xff0c;但是无法知道…...

redis未设置密码被植入挖矿脚本

最近一台测试linux响应速度贼慢&#xff0c;检查发现cpu消耗高达100%&#xff01;查看进程杀死后过段时间又重启了&#xff0c;一时间也摸不到头绪。无意间发现启动redis的时候cpu瞬间拉到了100%&#xff0c;主要就是zzh和newinit.sh两个脚本。百度了一下说是被植入了挖矿脚本&…...

轮询--一起学习吧之架构

一、定义 轮询&#xff08;Polling&#xff09;是一种CPU决策如何提供周边设备服务的方式&#xff0c;又称“程控输出入”&#xff08;Programmed I/O&#xff09;。这种方式是由CPU定时发出询问&#xff0c;依序询问每一个周边设备是否需要其服务&#xff0c;有即给予服务&am…...

【开发工具】Git模拟多人开发场景理解分支管理和远程仓库操作

我们来模拟一个多人多分支的开发场景。假设你有一个新的空白远程仓库,假设地址是 https://github.com/user/repo.git。 克隆远程仓库到本地 $ git clone https://github.com/user/repo.git这会在本地创建一个 repo 目录,并自动设置远程主机为 origin。 创建本地开发分支并推送…...

从零学习Linux操作系统 第三十一部分 ansible常用模块介绍

一、ansible运行模块的两种方式 Ad-Hoc方式 ##利用ansible命令直接完成管理&#xff0c;主要用于临时命令使用场景 playbook方式 ##ansible脚本&#xff0c;主要用于大型项目场景&#xff0c;需要前期的规划&#xff0c;相当于shell当中的脚本 二、如何查看模块帮助 ansible…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...