【项目】图书管理系统
目录
前言:
项目要求:
知识储备:
代码实现:
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;}
}
总结:大家最好自己实现一遍,实现的时候最好要明白自己在做什么,可以看看最后的结果来捋捋思路,可以看到我们使用到了接口,抽象类,包和继承的相关知识,只有在你使用他们的时候才会明白那里缺了。
结语:
其实写博客不仅仅是为了教大家,同时这也有利于我巩固自己的知识点,和一个学习的总结,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进,如果大家有所收获的话还请不要吝啬你们的点赞收藏和关注,这可以激励我写出更加优秀的文章。
相关文章:

【项目】图书管理系统
目录 前言: 项目要求: 知识储备: 代码实现: Main: Books包: Book: BookList: Operate包: Operate: addOperate: deleteOperate: exitOperate: findOperate:…...

华为OD机试 - 疫情扩散时间计算 - 矩阵(Java 2024 C卷 200分)
目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2024C卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷B卷C卷&am…...

[数据集][图像分类]棉花叶子病害分类数据集2293张4类别
数据集类型:图像分类用,不可用于目标检测无标注文件 数据集格式:仅仅包含jpg图片,每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数):2293 分类类别数:4 类别名称:["diseased_cotton_leaf"…...

《辐射4》是一款什么样的游戏 怎样在mac电脑上玩到《辐射4》辐射4攻略 辐射4开局加点 怎么在Mac电脑玩Steam游戏
辐射4(Fallout 4)是由Bethesda开发的一款动作角色扮演类游戏,为《辐射》系列游戏作品的第四代,于2015年11月10日发行。游戏叙述了主角一家在核爆当天(2077年10月23日),被Vault-Tec(避…...

视频推拉流EasyDSS平台直播通道重连无法转推的原因排查与解决
视频推拉流EasyDSS视频直播点播平台,集视频直播、点播、转码、管理、录像、检索、时移回看等功能于一体,可提供音视频采集、视频推拉流、播放H.265编码视频、存储、分发等视频能力服务。 用户使用EasyDSS平台对直播通道进行转推,发现只要关闭…...

Javaweb之SpringBootWeb案例之自动配置案例的自定义starter测试的详细解析
3.2.4.3 自定义starter测试 阿里云OSS的starter我们刚才已经定义好了,接下来我们就来做一个测试。 今天的课程资料当中,提供了一个自定义starter的测试工程。我们直接打开文件夹,里面有一个测试工程。测试工程就是springboot-autoconfigurat…...

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

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

如何为Android车载应用开发通知?
如何为Android车载应用开发通知?在开发车载应用的通知时,开发者需要考虑到驾驶安全,确保通知不会分散驾驶员的注意力。这通常意味着通知应该是非侵入性的,或者在不影响驾驶的情况下提供信息。开发者可以使用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 镜像仓库 三台机器均执行以下命令: 查看centos版本 [rootlocalhost Work]# cat /…...

网络安全: Kali Linux 进行 MSFvenom 程序利用
目录 一、实验 1.环境 2. Kali Linux 进行 MSFvenom 程序利用 3. 创建计划任务自动运行 MSFvenom 程序 二、问题 1.在线加密解密 2.MSF 运行失败 3.MobaXterm 连接Ubuntu 失败 一、实验 1.环境 (1)主机 表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;//;函数中的是形式参数 形参…...

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} xminF(x)21∥f(x…...

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

【笔记】Android ServiceStateTracker 网络状态变化逻辑及SPN更新影响
业务简介 在网络状态变化的时候(数据或WiFi),会更新SPN。 基于Android U的代码分析。 分类:SPN Data_Dic-的博客-CSDN博客 功能逻辑 状态说明 飞行模式下注册上WFC的话,注册状态MD上报 regState: NOT_REG_MT_NOT…...

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

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

轮询--一起学习吧之架构
一、定义 轮询(Polling)是一种CPU决策如何提供周边设备服务的方式,又称“程控输出入”(Programmed I/O)。这种方式是由CPU定时发出询问,依序询问每一个周边设备是否需要其服务,有即给予服务&am…...

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

从零学习Linux操作系统 第三十一部分 ansible常用模块介绍
一、ansible运行模块的两种方式 Ad-Hoc方式 ##利用ansible命令直接完成管理,主要用于临时命令使用场景 playbook方式 ##ansible脚本,主要用于大型项目场景,需要前期的规划,相当于shell当中的脚本 二、如何查看模块帮助 ansible…...

【Linux C | 网络编程】多播的概念、多播地址、UDP实现广播的C语言例子
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…...

HarmonyOS NEXT应用开发案例——滑动页面信息隐藏与组件位移效果
介绍 在很多应用中,向上滑动"我的"页面,页面顶部会有如下变化效果:一部分信息逐渐隐藏,另一部分信息逐渐显示,同时一些组件会进行缩放或者位置移动。向下滑动时则相反。 效果图预览 使用说明 向上滑动页面…...

ffmpeg 转码过程中参数含义
ffmpeg 转码过程中参数含义 frame 649 fps 73 q28.0 size 3072kB time00:00:25.88 bitrate 972.4kbits/ frame 694 fps 74 q28.0 size 3328kB time00:00:27.68 bitrate 984.9kbits/ frame 732 fps 74 q28.0 size 3584kB time00:00:29.20 bitrate1005.5kbits/ fram…...

探索c++——了解c++的魅力
前言:c是一门既面向对象又面向过程的语言。 不同于java纯粹的面向对象和c纯粹的面向过程。 造成c该特性的原因是c是由本贾尼大佬在c的基础上增添语法创建出来的一门新的语言。 它既兼容了c, 身具面向过程的特性。 又有本身的面向对象的特性。 面向对象和…...

Oracle常用语句语法
1 第一章Oracle命令 转载至 Oracle常用语句语法汇总 https://www.modb.pro/db/1759752946170548224 a) 系统管理员连接 conn */* as sysdba b) 查询当前用户 show user c) 创建新用户 create user 用户名 identified by 密码(密码不能以数字开头)。例如…...

时隔n年再度会看Vue,Git
时隔n年再度会看Vue,Git 曾经沧海难为水,除却巫山不是云。不知道这句话用在这里合不合适,好多东西在记忆中都淡化了。但是互联网确是有记忆的。研究以前项目的时候,翻看到gitee码云上托管的项目,就像是自己的孩子重新又回来了一样…...

SpringCloud-Zuul网关的使用
在SpringCloud中网关Zuul起什么作用? 在Spring Cloud中,Zuul 是一个边缘服务网关,起着以下作用:反向代理:Zuul 可以作为应用程序的反向代理服务器,接收客户端请求并将请求转发给相应的服务。这使得客户端可…...

mysql 中的一些重要函数
show create table user_profile 查看表结构 1.datediff(end_date,start_date)函数,now(), curdate() curtime() date_add(日期,interval num 时间) date_format(日期,格式) 4.select IFNULL(null,0); oracle 中nvl 函数 5.select IF(2 > 1, 2,0)ÿ…...

windows11配置电脑IP
windows11配置电脑IP 选择"开始>设置>“网络&Internet >以太网”。在 "属性"下,编辑IP地址,子网掩码,网关以及DNS。...

【JavaEE】_前端POST请求使用json向后端传参
目录 1. 关于json 2. 通过Maven仓库,将Jackson下载导入到项目中 3. 使用Jackson 3.1 关于readValue方法 3.2 关于Request.class类对象 3.3 关于request对象的属性类型 3.4 关于writeValueAsString 前端向后端传递参数通常有三种方法: 第一种&…...