图书管理系统

  ❤️❤️前言~🥳🎉🎉🎉

hellohello~,大家好💕💕,这里是E绵绵呀✋✋ ,如果觉得这篇文章还不错的话还请点赞❤️❤️收藏💞 💞 关注💥💥,如果发现这篇文章有问题的话,欢迎各位评论留言指正,大家一起加油!一起chin up!👍👍 

💥个人主页:E绵绵的博客
💥所属专栏:JAVASE题目练习  JAVASE知识点专栏  c语言知识点专栏   c语言题目练习

      现在我们将把之前学过的知识点总结做成一个小项目 ,叫图书管理系统,来看一下吧。 

 设计思路

 我们在设计系统前要遵循面向对象的原则:

1.找到对象

2.创建对象

3.使用对象

所以我们需要先理清自己的思绪,想明白需要创建的对象和需要实现的功能。

 

1. 首先,想清楚系统的界面。系统对于图书管理员来说是管理系统,对于普通用户来说是服务系统。所以我们针对管理员和普通用户所展示的界面是不同的。

 2.书的属性有书名,作者,价格,类型,是否被借出。所以我们可以将书的属性进行封装,同时设置一个书架类,用于存放书籍。设置一个书的数组可以解决。

3.管理员界面上,我们可以添加书籍,查找书籍,删除书籍,显示书籍和退出系统。

4.普通用户界面上,我们可以查找书籍,借阅书籍,归还书籍和退出系统。

5.所以我们可以将这些操作封装起来,设计成单独的类,但可以通过一些操作将这些功能分成两部分。

书籍和书架

  ❤️❤️首先我们面对对象时,找对象书肯定是一个对象,所以我们创建跟书有关的对象,如书和书架。现在我们就先来创建这两个对象吧:

书(Book)

❤️❤️我们创建一个book的包,用于存放与书有关的类。根据上述思路,我们可以在Book包中创建一个Book的类和一个Booklist (书架) 的类。首先创建一个book类,在book中写入书的有关属性,书名 (name) ,作者 (author)  ,价格 (price)  ,类型 (type) 以及是否被借出。我们通过封装,将属性前的访问修饰符设置为private权限,然后通过提供相应的get方法和set方法以及一个不包含是否被借出的构造方法(我们将是否被借出属性的类型设置为boolean,因为Boolean类型默认为false,所以可以不初始化),然后通过快捷键提供相应的toString方法的重写。

注意这些方法很多都能通过快捷键去生成,代码如下:

public class Book {private String name;private String  author;private  String  type;private  int   price;private   boolean  isborrowed;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 int getPrice() {return price;}public void setPrice(int price) {this.price = price;}

之所以用private修饰其书的属性,是为了体现书的密封性(书架中的属性也同理)

书架(BookList)

💕💕我们首先设置一个private权限的Book数组books,同时设置一个usedSize的变量,用于记录当前书架上存放了多少本书。我们写一个BookList的构造方法,同时将数组的长度初始化为10,然后通过快捷键设置userSize的getter and setter方法。注意不要使用编译器生成的Book数组books的getter and setter 方法,因为它针对的是books数组,并不是针对数组中存放的书,那并不是我们想要的。所以我们单独设置一个名为pos的数组下标参数,在getter方法中返回books的数组下标pos,在setter方法中,我们将 books数组的pos下标设置为一本书 。这样就能通过这两个方法去访问该数组的书成员。

现在请看以下代码:

public class BookList {private  Book[] books;private  int usedsize;//书架上目前存放的书量public BookList() {this.books=new Book[10];usedsize=4;this.books[0] = new Book("三国演义","罗贯中",20,"小说");this.books[1] = new Book("西游记","吴承恩",9,"小说");this.books[2] = new Book("红楼梦","曹雪芹",19,"小说");
this.books[3]=new Book("Java","xx",18,"学习资料");}public int getUsedsize() {return usedsize;}public void setUsedsize(int usedsize) {this.usedsize = usedsize;}public Book getBook(int i){return books[i];}public  void   setBook(int i,Book book){books[i]=book;}
}

这里的属性也是用private修饰,呈封装性。

 用户

💕💕 除此之外,除了书是对象,图书管理系统也要人使用对吧,所以人也是个对象。并且因为身份的不同,分为普通用户和管理员。而又因为都是人,所以会有一些相同点。所以我们就创建一个子类user ,两个父类。

user(用户抽象类)(子类) 

💕💕在普通用户和管理员用户中存在许多共性,因此我们这里设置一个抽象类供普通用户和管理员用户来继承使用,并且将其变为抽象类更方便继承。

abstract public class User {protected String name;protected IOperation[] iOperations;abstract public   int  menu();public User(String name) {this.name = name;}public  void useoperation(int choice,BookList bookList){IOperation iOperation = iOperations[choice];iOperation.work(bookList);}
}

 管理员类(Administrator)

💕💕我们设置管理用户的菜单,再对应着菜单在构造方法中设置接口类型的数组的具体操作

​
public class Administrator extends User{public Administrator(String name) {super(name);iOperations = new IOperation[]{new ExitOperation(),new FindOperation(), new AddOperation,new DeleteOperation(),new ShowOperation()};}@Overridepublic int menu() {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.println("请输入你的操作:");Scanner scanner = new Scanner(System.in);int choice = scanner.nextInt();return choice;}
}​

 普通用户(NormalUser)

💕💕它和管理员类的操作大致相同,这里就不过多讲述了,直接上代码

​
public class NormalUser extends User {public NormalUser( String name){super(name);iOperations=new IOperation[] {new ExitOperation(),new FindOperation(),new BorrowOperation(),new RetrunOperation()};}public int menu() {System.out.println("********普通用户菜单********");System.out.println("1.查找图书");System.out.println("2.借阅图书");System.out.println("3.归还图书");System.out.println("0.退出系统");System.out.println("***************************");System.out.println("请输入你的操作");Scanner scanner=new Scanner(System.in);int choice=scanner.nextInt();return  choice;}}​

 对书籍的相关操作

❤️❤️我们知道面对对象分为三步,最后一步是使用对象,而这里就是对于对象的使用。其中有很多操作,我们来看一下吧。

操作接口(IOperation)

❤️❤️所有的操作都是要对于书架进行操作的,所以我们在这里提供一个接口供不同操作来实现,并且给他们传入书架类的参数,代码如下:

​
public interface IOperation {public void work(BookList bookList);
}​

 借阅图书(BorrowOperation

❤️❤️首先,我们需要让用户输入想要借阅的图书的名字,然后我们挨个遍历书架上的书,如果有,那就可以借,将书籍的借阅状态改为true就可以,如果没有就告诉用户没有此书,无法借阅。

public class BorrowOperation implements IOperation{@Override
public void work(BookList bookList) {System.out.println("该操作进行中,请输入要借阅的书");Scanner scanner=new Scanner(System.in);String name  =scanner.nextLine();for (int i = 0; i < bookList.getUsedsize() ; i++) {if ((bookList.getBook(i).getName()).equals(name)){if(bookList.getBook(i).getIsborrowed()==true) {System.out.println("该书已被借出,现在没有这本书");return;}else {System.out.println("该书借出后请及时归还");bookList.getBook(i).setIsborrowed(true);return;}}if(i== bookList.getUsedsize()-1){System.out.println("未查找到该书");}}}
}

归还图书(ReturnOperation)

 ❤️❤️和借阅图书思路相似,这里不多说了。直接上代码:

public class RetrunOperation implements  IOperation {@Overridepublic void work(BookList bookList) {System.out.println("该操作进行中,请输入要归还的书");Scanner scanner=new Scanner(System.in);String name  =scanner.nextLine();for (int i = 0; i < bookList.getUsedsize() ; i++) {if ((bookList.getBook(i).getName()).equals(name)) {bookList.getBook(i).setIsborrowed(false);System.out.println("该书归还成功");return;}}System.out.println("不存在该书");}
}

 查找图书(FindOperation)

❤️❤️ 查找功能和遍历类似,只要利用equals关键字比较字符串输出就行。在 Findioperation 类中,先输入要查找的书名,遍历所有的书,比较书名,书名一样输出即可。 

public class FindOperation implements IOperation {@Overridepublic void work(BookList bookList) {System.out.println("该操作进行中,请输入要查找的书");Scanner scanner = new Scanner(System.in);String name = scanner.nextLine();for (int i = 0; i < bookList.getUsedsize(); i++) {if ((bookList.getBook(i).getName()).equals(name)) {System.out.println("找到该书");System.out.println(bookList.getBook(i));return;}}System.out.println("没找到该书");}
}

显示图书 (ShowOperation)

❤️❤️ 遍历整个书架,然后挨个打印输出图书信息就可以了。

public class ShowOperation implements IOperation{@Overridepublic void work(BookList bookList) {System.out.println("该操作进行中,将展示所有书的信息");for (int i = 0; i < bookList.getUsedsize() ; i++) {System.out.println(bookList.getBook(i));}
}}

 添加图书(AddOperation)

❤️❤️首先,我们需要让用户输入想要添加的图书的相关信息,然后我们为用户输入的图书新建一个对象,接下来就是合法性判断,我们拿刚才新建的图书对象和书架上的每一个图书对象进行遍历对比,如果没有重复的图书就可以存入这本书,要存入这本书就调用刚才书架类中提供的方法setBooks,在新加一本书籍后,对应的书籍数量也得增加,也就是调用setUesdSize方法来增加书籍的数量。

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.nextLine();if(bookList.getUsedsize()==10) {System.out.println("书架满了,无法添加");return;}for (int i = 0; i < bookList.getUsedsize(); i++) {if ((bookList.getBook(i).getName()).equals(name)) {System.out.println("该书在书架中已有,无需添加");return;}}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,price,type);bookList.setBook(bookList.getUsedsize(),book );System.out.println("添加成功");bookList.setUsedsize(bookList.getUsedsize()+1);
}}

这里有个重要的点,对于新建对象时的输入,必须nextint在最后面,否则会导致以下现象。

这里只接受了三个,第四个还没输入就结束了。所以应该把nextint放在最后,这样就不会有异常现象。

对于其原因,这里有篇文章可以解释以上现象java中程序逻辑控制-CSDN博客,在这部分有提到过该现象。

删除图书 (DeleteOperation)

❤️❤️思路:首先找到有没有这本书,如果找到了,这书后边的书就从后往前直接覆盖掉之前的书数据,然后将usedsize减一就行了,从而最后一个数据我们就使用不了(之后的其他操作会将最后一个数据覆盖掉)。

所以在循环时,i 要小于usedSize - 1,,如果大于等于usedsize-1的话,就会越界访问数组之外的数据,从而报错。

public class DeleteOperation implements IOperation{@Overridepublic void work(BookList bookList) {System.out.println("该操作进行中,请输入要删除的书");Scanner scanner = new Scanner(System.in);String name = scanner.nextLine();int deletesize=0;for (int i = 0; i < bookList.getUsedsize(); i++) {if ((bookList.getBook(i).getName()).equals(name)) {deletesize=i;break;}if(i== bookList.getUsedsize()-1){System.out.println("该书架中不存在该书");return;}}for (int i = deletesize; i < bookList.getUsedsize()-1 ; i++) {bookList.setBook(i,bookList.getBook(i+1));}bookList.setUsedsize(bookList.getUsedsize()-1);System.out.println("删除"+name+"成功");}}

退出系统 

❤️❤️最简单的一个操作,System.exit(0)代表着结束程序,所以我们只需要使用该方法就能退出系统。

public class ExitOperation implements IOperation{@Overridepublic void work(BookList bookList) {System.out.println("系统已退出");System.exit(0);//作用是结束该程序}
}

 main类

所以有了前面的这些基础,我们就将它们组合起来利用,形成这个main类。

我们在main类中除了有main方法外,还要设置一个登录程序的方法,登录管理员我们就新建一个管理员对象,登录普通用户我们就新建一个普通用户对象,然后我们根据用户的输入来调用我们菜单中的选项,我们通过设置接口数组从而来操作它。

public class Main {public static User login() {System.out.println("请输入你的名字");Scanner scanner = new Scanner(System.in);String name = scanner.nextLine();System.out.println("请确认你的身份  1:普通用户 2:管理员 ");while (true) {int choice = scanner.nextInt();if (choice == 1) {return new NormalUser(name);} else if (choice == 2) {return new Administrator(name);} else {System.out.println("只能输入1或2,请重新输入");continue;}}}public static void main(String[] args) {BookList bookList=new BookList();User  user =login();while (true){int choice= user.menu();user.useoperation(choice,bookList);
}
}

总结 

 所以这就是我们的图书管理系统,如果想看完整的代码,我这里有我码云的链接,大家可以看一下:

_2024_4_6/src · Eason绵绵/JAVASE代码仓库 - 码云 - 开源中国 (gitee.com)

本篇文章制作不易,还请各位大佬给个三连,点点关注,点点赞,评评论,谢谢各位大佬们呀,一起加油❤️❤️~🥳🎉🎉🎉

​​​​​​​

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

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

相关文章

sqlalchemy中Datetime的创建时间-修改时间之default|server_default|onupdate

default vs. server_default 的区别 default 这个属性 &#xff0c;就是默认生成orm 对象,如果某个字段没有 传值&#xff0c;就使用default 值&#xff0c;然后写入到数据库中。 server_default 这个属性&#xff0c;要求是一个str, unicode 类型。 用来生成表结构的时候&am…

Vue - 你会在同一个元素上使用v-for和v-if吗

难度级别:初级及以上 提问概率:50% 在初学者看来,v-for和v-if同时使用是非常方便的,二者共同使用的常见场景有两种。例如有两个列表,分别用于渲染学生数据和老师数据,然后有两个单选按钮,用于切换当前页面中需要展示学生列表还是老师列…

鸿蒙HarmonyOS 与 Android 的NDK有什么不一样?

1. 序言 就像开发Android要用Android Studio一样&#xff0c;Android Studio&#xff08;简称AS&#xff09;其实是基于IDEAgradle插件android插件开发而来。 鸿蒙系统&#xff0c;你可以认为它和android有点像&#xff0c;但又是超越android的存在&#xff0c;除了手机&…

【洛谷题解】 P10337 [UESTCPC 2024] 操作序列

分析 首先&#xff0c;我们知道&#xff0c;当这 n n n 个数全部相等时&#xff0c; k k k 的最大值就是 n n n。 那如果不相等呢&#xff0c; k k k 就不可能为 n n n 得值了&#xff0c;因为每次他都要选择 k k k 个不同位置上的数乘上一个相同的数&#xff0c;把几个不…

nginx目录sites-enabled和sites-available介绍

模块简介&#xff1a; 在Nginx中&#xff0c;/etc/nginx/sites-enabled 目录和 /etc/nginx/sites-available 目录通常用于组织虚拟主机配置文件&#xff0c;这些文件描述了不同站点的设置&#xff0c;例如域名、目录结构等。 /etc/nginx/sites-available 目录&#xff1a;存放…

go-zero整合单机版Redis并实现增删改查

go-zero整合单机版Redis并实现增删改查 本教程基于go-zero微服务入门教程&#xff0c;项目工程结构同上一个教程。 go-zero微服务入门教程&#xff08;点击进入&#xff09; 本教程主要实现go-zero框架整合单机版Redis&#xff0c;并暴露接口实现对Redis数据的增删改查。 本…

Oracle容器镜像制作

对于 Oracle 数据库的容器镜像制作&#xff0c;oracle 官方提供了 Dockerfile 文件和制作脚本的&#xff08;https://github.com/oracle/docker-images&#xff09;。这里以 12c 为例看看怎么使用。 下载官方提供的 Dockerfile 文件和制作脚本 $ git clone https://github.com/…

笛卡尔树[天梯赛二叉树专项训练]

文章目录 题目描述思路AC代码 题目描述 输入样例1 6 8 27 5 1 9 40 -1 -1 10 20 0 3 12 21 -1 4 15 22 -1 -1 5 35 -1 -1 输出样例1 YES 输入样例2 6 8 27 5 1 9 40 -1 -1 10 20 0 3 12 11 -1 4 15 22 -1 -1 50 35 -1 -1 输出样例2 NO思路 见注释 AC代码 #include <bits/st…

【重学C语言】五、分支结构

【重学C语言】五、分支结构 三种结构分支结构if 语句示例 1&#xff1a;基本的 if 语句 if...else 语句示例 2&#xff1a;if...else 语句 嵌套 if示例 3&#xff1a;嵌套的 if 语句 if 语句与逻辑运算符示例 4&#xff1a;使用逻辑与&#xff08;&&&#xff09;示例 5…

搭建python编译环境

目录 1.安装依赖包 2.安装失败进行换源 3. 更新系统 通过C 语言调用 Python 代码&#xff0c;需要先安装 libpython3 的 dev 依赖库&#xff08;不同的 ubuntu 版本下&#xff0c; python 版本 可能会有差异&#xff0c; 比如ubuntu 22.04 里是 libpython3.10-dev &#xff09…

2024/4/1—力扣—最小高度树

代码实现&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ struct TreeNode* buildTree(int *nums, int l, int r) {if (l > r) {return NULL; // 递归出口}struct…

题解:CF1941C(C. Rudolf and the Ugly String)

题解&#xff1a;CF1941C&#xff08;C. Rudolf and the Ugly String&#xff09; 题目翻译&#xff1a;给定一个字符串&#xff0c;请你求出最少需要删除几个字符才能使得该字符串内不存在 map 和 pie。 我们可以先在该字符串内找到所有的子串 mapie&#xff0c;并删除中间的…

[StartingPoint][Tier1]Sequel

Task 1 During our scan, which port do we find serving MySQL? (在扫描过程中&#xff0c;我们发现哪个端口为 MySQL 提供服务&#xff1f;) 3306 Task 2 What community-developed MySQL version is the target running? (目标正在运行哪个社区开发的 MySQL 版本&…

Python实现【坦克大战】+源码分享

写在前面&#xff1a; 坦克大战&#xff0c;这款经典的电子游戏&#xff0c;无疑是许多80后和90后心中不可磨灭的童年记忆。它不仅仅是一款游戏&#xff0c;更是那个时代科技娱乐方式的缩影&#xff0c;见证了电子游戏行业的起步与发展。 在那个电脑和网络尚未完全普及的年代…

c语言实现2048小游戏

#include <stdio.h> #include <stdlib.h> #include <time.h> #include <conio.h>int best 0 ;// 定义2048游戏的结构体 typedef struct { int martix[16]; // 当前4*4矩阵的数字 int martixPrior[16]; // 上一步的4*4矩阵的数字 int emptyIndex[16…

LeetCode 1017. 负二进制转换

解题思路 相关代码 class Solution {public String baseNeg2(int n) {if(n0) return "0";String s"";while(n!0)if(Math.abs(n)%20){nn/(-2);ss0;}else{ss1; n (n-1)/(-2);}String t reverse(s);return t;}public String reverse(String s){Str…

嵌入式培训4-7

今日作业&#xff1a; 1、有一个隧道&#xff0c;全长5公里&#xff0c;有2列火车&#xff0c;全长200米&#xff0c; 火车A时速 100公里每小时 火车B时速 50公里每小时 现在要求模拟火车反复通过隧道的场景(不可能2列火车都在隧道内运行) 2、有一个隧道&#xff0c;全长5公里&…

前端三剑客 —— JavaScript (第一节)

目录 回顾内容 1.弹性布局 2.网格布局 JavaScript 概述 发展 浏览器 什么是Javascript JavaScript 能干什么 JavaScript需要的环境 JavaScript初体验 基本数据 JS书写方式 行内JS 页面JS 外部JS 1&#xff09;创建外部JS文件 2&#xff09;编写页面 对话框 警…

达梦数据库的快速加列参数ALTER_TABLE_OPT使用

达梦数据库的表数据量较大时&#xff0c;在线直接修改表结构新增字段会很慢 现象&#xff1a;开发人员测试环境增加一个字段耗时7分钟&#xff0c;数据量仅仅2千万&#xff1b; 为了解决这一问题&#xff0c;达梦数据库提供一个动态会话级参数&#xff1a;ALTER_TABLE_OPT&am…

vue中三种watcher

在分析之前我们先来看看&#xff0c;vue中都有哪些Watcher种类呢&#xff1f;以及分别在什么时候创建呢&#xff1f;从vue源码里面看&#xff0c;Watcher是一个公共类&#xff0c;在不同的地方去初始化Watcher就代表不同类的Watcher。主要分为以下三类&#xff1a; computed w…