各位读者好, 我是小陈, 这是我的个人主页
小陈还在持续努力学习编程, 努力通过博客输出所学知识
如果本篇对你有帮助, 烦请点赞关注支持一波, 感激不尽
希望我的专栏能够帮助到你:
JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等
Java数据结构: 顺序表, 链表, 堆, 二叉树, 二叉搜索树, 哈希表等
JavaEE初阶: 多线程, 网络编程, TCP/IP协议, HTTP协议, Tomcat, Servlet, Linux, JVM等(正在持续更新)
前几篇文章介绍了:
1️⃣Java的【类和对象】
2️⃣面向对象的三大特征【封装】,【继承】,【多态】
3️⃣Java的【接口】
本篇将结合之前所讲的【面向对象】知识,实现一个简易版的 “图书管理系统” ,来加强巩固这一部分相关知识的掌握
具体的代码实现可能和小伙伴们认为的逻辑不同噢,毕竟条条大路通罗马~
提示1:本篇是非常非常基础且简易粗糙的小练习,如有大佬已经掌握了高级的实现方式,请请轻喷!!也欢迎小伙伴们评论区讨论~
提示2:本篇只实现主要的功能,很多细节可能不会完美的处理,如果小伙伴们发现一些影响不大的bug请勿喷,完善bug不是本篇的主要目标
在【类和对象】文章中说过,在Java的世界里一切皆对象
所以要想学好面向对象语言,首先需要有把事物抽象出来的能力
对于图书管理系统而言,对象都有哪些呢?
1️⃣简单来说可以分为:人和书
2️⃣并且系统中又存放着很多本书,所以应该用数组来存放书,所以还应该有一个书架
本篇以简易练习为主,所以只设置1️⃣个书架,书架上只存本书
暂时确定好了 人,书,书架 这3️⃣个对象之后,问题又来了:
我们应该如何自定义一个类,来描述这个对象呢?
这就要思考这三个类分别需要什么成员属性和成员方法
暂时我们需要定义的类有:Book,BookShelf,User
目前,Book类 需要有:
成员属性: “bookName”,“author”,“price”,“isBorrowed”
构造方法:初始化 Book
❗️❗️❗️为了体现【封装】特性,把这些成员属性用 private 修饰❗️❗️❗️
下面其他类中的成员属性同理
成员方法:getter 和 setter (体现封装)
目前, BookShelf 类 需要有:
成员属性: “Book[ ] books” ( Book 类型的数组), “size”(书架上存放书的实际个数)
类就是一种类型,我们定义了一个 Book 类之后,Book 就是一个变量的类型✅
例如:定义一个存放 整形 的数组 : int[ ] + 变量名
所以定义一个存放 Book 的数组 :Book[ ] + 变量名
构造方法:初始化 BookShelf (为了方便,默认存放3️⃣本书)
成员方法:getter 和 setter
❓❓❓在定义 User 这个类之前,需要思考为什么要有 “人” 这个对象
图书管理系统需要 “人” 来操作,那么 “人” 的身份又分为两种:“管理员”,**“用户”**身份,操作的选项也不同:
“管理员” 需要的操作:显示图书信息、增加图书信息、删除图书信息、查询图书信息、退出系统
“用户” 需要的操作:查询图书信息、借阅图书、归还图书、退出系统
⚠️⚠️⚠️我们希望:
在登录时,让使用者输入姓名,并选择身份,根据身份的不同,提供不同的操作选项这不就是 多态 的思想吗✅
所以我们还需定义 “Administrator” , “Customer” 两个子类,来继承 User 这个父类(继承是多态的前提)
这样就可以在 “Administrator” , “Customer” 两个子类中分别定义 menu 成员方法,来打印对应的操作菜单
目前, User 类 需要有:
成员属性: “name” 即可
构造方法:初始化 name
成员方法:menu,子类用来打印操作菜单,所以 User 作为父类,只需要用 abstract 修饰即可
在 “Administrator” , “Customer” 两个子类中,需要提供
构造方法:帮助父类初始化 name
分别提供成员方法: menu
上面说到,不同的身份会对应不同的操作菜单,根据这两份操作菜单中的操作选项就可以抽象出一个接口: Operate
而接口不能单独使用,必须被 “类” 实现,所以我们就可以把:
“管理员” 需要的操作:显示图书信息、增加图书信息、删除图书信息、查询图书信息、退出系统
“用户” 需要的操作:查询图书信息、借阅图书、归还图书、退出系统
这些操作,分别定义成 类 :
“Add” 增加
“Delete” 删除
“Show” 显示
“Find” 查找
“Borrow” 借阅
“Return” 归还
“Exit” 退出
让这些 类 都 实现 Operate这个接口,在 Operate 接口中 定义一个抽象方法: operate(),这样就只需要在这些 类 中重写 operate() 方法即可✅
大概的框架我们已经分析过了,下面我们一点点解析代码
首先我们把刚刚分析的大致框架写出来:
我们新建一个 book 包,包中新建 Book 类和 BookShelf 类:
public class Book {
private String bookName;
private String author;
private double price;
private boolean isBorrowed;
// 构造方法
public Book(String bookName, String author, double price) {
this.bookName = bookName;
this.author = author;
this.price = price;
}
// getter 和 setter
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public boolean getIsBorrowed() {
return isBorrowed;
}
public void setIsBorrowed(boolean isBorrowed) {
this.isBorrowed = isBorrowed;
}
}
可以看到构方法中没有 isBorrowed 这个参数,是因为 boolean 类型的变量即使不初始化,系统也会赋给一个默认值,默认为 “false”
public class BookShelf {
private Book[] books = new Book[10];
private int size;
// 构造方法
public BookShelf() {
books[0] = new Book("瓦尔登湖", "张三", 39.9);
books[1] = new Book("百年孤独", "李四", 49.9);
books[2] = new Book("赎罪", "王五", 38.8);
this.size = 3;
}
//getter 和 setter
public Book[] getBooks() {
return books;
}
public void setBooks(Book[] books) {
this.books = books;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
在构造方法中默认存放3️⃣本书即可
注意: getBooks 方法的返回值是 Book[ ] ,也就是说我们得到的是 存放书的整个数组
我们接下来再新建一个 user 包,在 user 包中新建一个父类 User ,再新建两个子类 “Administrator” , “Customer” ,分别继承 User 父类
public abstract class User {
protected String name;
public User(String name) {
this.name = name;
}
// 抽象方法,在子类中分别实现
public abstract void menu();
}
public class Administrator extends User {
// 构造方法
public Administrator(String name) {
super(name);
}
public void menu() {
System.out.println("——————————————");
System.out.println("hello " + this.name );
System.out.println("1.显示图书信息" );
System.out.println("2.增加图书信息" );
System.out.println("3.删除图书信息" );
System.out.println("4.查询图书信息" );
System.out.println("0.退出系统" );
System.out.println("——————————————");
}
}
public class Customer extends User{
// 构造方法
public Customer(String name) {
super(name);
}
public void menu() {
System.out.println("——————————————");
System.out.println("hello " + this.name);
System.out.println("1.查询图书信息");
System.out.println("2.借阅图书");
System.out.println("3.归还图书");
System.out.println("0.退出系统");
System.out.println("——————————————");
}
}
我们接下来再新建一个 operate 包,在 operate 包中新建一个接口 Operate ,再新建所需操作对应的类 :
“Add” 增加
“Delete” 删除
“Show” 显示
“Find” 查找
“Borrow” 借阅
“Return” 归还
“Exit” 退出
public interface Operate {
// 抽象方法
void operate(BookShelf bookShelf);
}
重要的事说第二遍!
Operate 接口中的抽象方法不需要具体实现,因为下面的类都 implements 了 Operate 接口,所以只需要在各自类中 重写 即可
下面暂时不重写 operate 方法,先写大致框架
public class Add implements Operate {
@Override
public void operate(BookShelf bookShelf) {
}
}
public class Delete implements Operate {
@Override
public void operate(BookShelf bookShelf) {
}
}
public class Show implements Operate {
@Override
public void operate(BookShelf bookShelf) {
}
}
public class Find implements Operate {
@Override
public void operate(BookShelf bookShelf) {
}
}
public class Borrow implements Operate {
@Override
public void operate(BookShelf bookShelf) {
}
}
public class Return implements Operate {
@Override
public void operate(BookShelf bookShelf) {
}
}
public class Exit implements Operate {
@Override
public void operate(BookShelf bookShelf) {
}
}
上面都写完之后,在 scr 包或者 user 包下面新建一个 Test 类,用来写 main 方法及其他相关代码
(博主是在 src 下面新建 Test 类)
从 Test 类开始解析 ~~ !!
我们希望在程序运行起来后,让使用者输入姓名,选择(输入)身份,根据身份不同,给使用者显示不同的菜单 (多态思想),让使用者输入操作选项,根据选择,执行对应的程序( operate 方法)(接口操作)
可以总结为三部分:
1️⃣输入姓名,选择身份 (登录)
2️⃣打印菜单
3️⃣选择操作
第1️⃣部分:登录
public static User login() {
System.out.println("请输入你的姓名:");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
System.out.println("请选择你的身份: 1->管理员 2->顾客");
Scanner sc = new Scanner(System.in);
int idOption = scanner.nextInt();
if(idOption == 1) {
return new Administrator(name);
}else {
return new Customer(name);
}
}
public static void main(String[] args) {
// 向上转型
User user = login();
}
根据 idOption 的不同,返回值处 new 对应的身份的对象,在 main() 方法中用User 父类接收子类,实现向上转型,实际上是为了接下来的多态做准备️
第2️⃣部分:打印菜单
....
public static int printMenu(User user) {
user.menu(); // 实现多态
System.out.println("请选择你的操作:");
Scanner scanner = new Scanner(System.in);
return scanner.nextInt();
}
public static void main(String[] args) {
// 向上转型
User user = login();
// 打印菜单
printMenu(user);
}
在 printMenu() 方法中第一行就实现了多态,执行子类对象的 menu() 方法 ,发生了动态绑定
最后根据菜单提示,输入对应操作的序号,作为返回值✅
这里在 main 方法中暂时没有接收返回值,是为了抛出一个疑问:
我们需要接收返回值吗,要返回值有什么用?
废话!!当然需要返回值,没有返回值,我咋知道你选择的哪个序号,我咋给你执行对应的 operate() 方法???
好, 问题就出现在这❗️❗️❗️本篇最最最最关键点来了❗️❗️❗️
我们需要根据返回值 (数字序号) ,来执行对应的 operate() 方法
像不像根据下标(数字序号)访问数组?而 接口也是一种引用数据类型
所以我们可以定义一个接口类型的数组❗️❗️❗️,数组中按需求存放 “Add” ,“Delete” ,“Show” ,“Find” ,“Borrow” ,“Return” ,“Exit”
所以我们在 User 父类中:
1️⃣补充一个成员属性:Operate 数组,只声明即可,在子类中利用构造方法帮助父类进行初始化这个数组(如图),因为 Operate 数组中的元素都是引用数据类型,所以初始化数组的过程就是实例化对象(图中没有写 new 关键字)
2️⃣补充一个成员方法:doOperate() ,如图中最后一行所示,利用下标访问对应的类中的 operate 方法
public abstract class User {
protected String name;
protected Operate[] operates; //数组,存放不同的操作(对象)
public User(String name) {
this.name = name;
}
public abstract void menu();
// 重点!
public void doOperate(int operateOption, BookShelf bookShelf) {
this.operates[operateOption].operate(bookShelf);
}
}
补充了一个成员属性和成员方法
在 doOperate() 方法中,我们操作的对象是存放书的数组(书架),所以将定义的 bookshelf 作为参数传递
public class Administrator extends User {
// 构造方法
public Administrator(String name) {
super(name);
this.operates = new Operate[]{
new Exit(),
new Show(),
new Add(),
new Delete(),
new Find()
};
}
public void menu() {
System.out.println("——————————————");
System.out.println("hello " + this.name );
System.out.println("1.显示图书信息" );
System.out.println("2.增加图书信息" );
System.out.println("3.删除图书信息" );
System.out.println("4.查询图书信息" );
System.out.println("0.退出系统" );
System.out.println("——————————————");
}
}
根据菜单补充了构造方法,初始化Operate数组
public class Customer extends User{
// 构造方法
public Customer(String name) {
super(name);
this.operates = new Operate[]{
new Exit(),
new Find(),
new Borrow(),
new Return(),
};
}
public void menu() {
System.out.println("——————————————");
System.out.println("hello " + this.name);
System.out.println("1.查询图书信息");
System.out.println("2.借阅图书");
System.out.println("3.归还图书");
System.out.println("0.退出系统");
System.out.println("——————————————");
}
}
根据菜单补充了构造方法,初始化Operate数组
BB那么多,到现在 main 方法中的第3️⃣部分:执行操作就很简单了:
定义一个 operateOption(操作选项)变量 接收 printMenu() 方法的返回值
再调用 user 对象中的 doOperate() 方法即可
当然需要将 操作选项 和 书架 作为参数传递
最后记得加上 while 循环噢
public static void main(String[] args) {
BookShelf bookShelf = new BookShelf();
// 向上转型
User user = login();
while(true) {
// 打印菜单 选择操作 【多态】
int operateOption = printMenu(user);
//执行操作
user.doOperate(operateOption, bookShelf);
}
}
至此,我们的 user 包和 Test 类就全部写完了
完整的 Test 类:
public class Test {
public static User login() {
System.out.println("请输入你的姓名:");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
System.out.println("请选择你的身份: 1->管理员 2->顾客");
Scanner sc = new Scanner(System.in);
int idOption = scanner.nextInt();
if(idOption == 1) {
return new Administrator(name);
}else {
return new Customer(name);
}
}
public static int printMenu(User user){
user.menu();
System.out.println("请选择你的操作:");
Scanner scanner = new Scanner(System.in);
return scanner.nextInt();
}
public static void main(String[] args) {
BookShelf bookShelf = new BookShelf();
// 登录 接收返回值时发生向上转型
User user = login();
while(true) {
// 打印菜单 选择操作 【多态】
int operateOption = printMenu(user);
//执行操作
user.doOperate(operateOption, bookShelf);
}
}
}
接下来就只剩下 operate 包中的几个 表示操作” 的类了
public class Show implements Operate {
@Override
public void operate(BookShelf bookShelf) {
System.out.println("图书信息如下:");
bookShelf.printBookShelf(bookShelf);
}
}
原本应该在 Show 这个类中遍历书架并打印相关信息,但后续会多次需要遍历并打印
所以为了避免代码冗余❎,把 printBookShelf() 单独写成一个方法✅,在 BookShelf 类中实现(同时和 Test 类中的 printMenu() 方法对应)
⚠️没有必要写成 Static 静态方法,因为我们在main方法中一定会实例化bookShelf对象,所以通过对象访问 printBookShelf() 也完全可行
public void printBookShelf(BookShelf bookShelf) {
int size = bookShelf.getSize();
for (int i = 0; i < size; i++) {
System.out.print(i + 1 + ": ");
System.out.println("书名: "+ bookShelf.getBooks()[i].getBookName() + " "
+ "作者: " + bookShelf.getBooks()[i].getAuthor() + " "
+ "价格:"+ bookShelf.getBooks()[i].getPrice() + "元 "
+ (bookShelf.getBooks()[i].getIsBorrowed()?" 已背借出":" 未被借出"));
}
}
这里最后一行,打印 isBorrowed 的值时还用到了一个三目运算符 再打打基础哈哈哈哈哈
public class Add implements Operate {
@Override
// 重写 Operate 接口中的 operate 方法
public void operate(BookShelf bookShelf) {
System.out.println("请依次输入:书名、作者、价格");
Scanner scanner1 = new Scanner(System.in);
String newBookName = scanner1.nextLine();
Scanner scanner2 = new Scanner(System.in);
String newAuthor = scanner2.nextLine();
Scanner scanner3 = new Scanner(System.in);
double newPrice = scanner3.nextDouble();
int size = bookShelf.getSize();
bookShelf.getBooks()[size] = new Book(newBookName, newAuthor, newPrice);
System.out.println("增加成功\n");
bookShelf.setSize(++size);
}
}
这里我们默认 添加的图书位置在最后一位
分为四步:
1️⃣从控制台输入相关信息( isBorrowed 不用输入,默认是 false )
2️⃣new 一个 Book 类的对象,利用构造方法初始化图书信息
3️⃣将 new 的新对象的引用赋给 bookShelf.getBooks()[size]
bookShelf.getBooks() 这个方法的返回值是Book[ ],是一个数组,所以后面通过 “[ ]” 操作符就可以访问数组内的元素,size 下标就是最后一个元素
4️⃣通过 setter 方法把被封装的 size 加1
public class Delete implements Operate {
@Override
// 重写 Operate 接口中的 operate 方法
public void operate(BookShelf bookShelf) {
int size = bookShelf.getSize();
bookShelf.printBookShelf(bookShelf);
System.out.print("请输入您要删除第几本书:");
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();
for (int i = num - 1; i < size - 1; i++) {
bookShelf.getBooks()[i] = bookShelf.getBooks()[i + 1];
}
bookShelf.setSize(--size);
System.out.println("删除成功\n");
bookShelf.printBookShelf(bookShelf);
}
}
这里删除某一个位置的图书,利用的思想是将后一个位置的图书信息覆盖到前一个位置上,注意 顺序 是 从前往后
注意:
for 循环的判断条件是 i < size - 1 ,不能是 <=
因为:此时的书架只放了 3️⃣本书,如果❗️❗️书架上放满了书,size 为❗️❗️, bookShelf.getBooks()[i] = bookShelf.getBooks()[i + 1];
访问 i + 1 下标时就会数组越界❌
public class Find implements Operate {
@Override
// 重写 Operate 接口中的 operate 方法
public void operate(BookShelf bookShelf) {
System.out.println("请输入你要查询的书名");
Scanner scanner = new Scanner(System.in);
String targetName = scanner.nextLine();
int size = bookShelf.getSize();
for (int i = 0; i < size; i++) {
if(bookShelf.getBooks()[i].getBookName().equals(targetName)) {
System.out.println("该书籍信息如下:");
System.out.println("书名: "+ bookShelf.getBooks()[i].getBookName() + " "
+ "作者: " + bookShelf.getBooks()[i].getAuthor() + " "
+ "价格: "+ bookShelf.getBooks()[i].getPrice() + "元 "
+ "是否被借出: " + bookShelf.getBooks()[i].getIsBorrowed());
return;
}
}
System.out.println("未查询到此书\n");
}
}
这个很好理解,不多赘述
bookShelf.getBooks()[i].getBookName() 这行代码乍一看很长实际上也很好理解:
1️⃣首先 bookShelf.getBooks() 通过对象访问得到书架这个成员属性(得到数组)
2️⃣再通过下标 i 访问到具体的那本书
3️⃣再通过 “点号” 访问这个 Book 对象的getBookName() 成员方法
public class Exit implements Operate {
@Override
// 重写 Operate 接口中的 operate 方法
public void operate(BookShelf bookShelf) {
System.out.println("感谢使用本系统,再见!");
System.exit(0);
}
}
这里只需要用到一个 System.exit(0) 库方法即可,程序正常结束时就会在控制台输出 “Process finished with exit code 0” 不过多做研究 ~
public class Borrow implements Operate {
@Override
// 重写 Operate 接口中的 operate 方法
public void operate(BookShelf bookShelf) {
System.out.println("请输入您要借阅的书名");
Scanner scanner = new Scanner(System.in);
String borrowName = scanner.nextLine();
int size = bookShelf.getSize();
for (int i = 0; i < size; i++) {
if (bookShelf.getBooks()[i].getBookName().equals(borrowName)) {
if(bookShelf.getBooks()[i].getIsBorrowed()) {
// if (bookShelf.getBooks()[i].getIsBorrowed() == false) {
System.out.println("抱歉,该书已被借出\n");
return;
}else {
bookShelf.getBooks()[i].setIsBorrowed(true);
System.out.println("借阅成功\n");
return;
}
}
}
System.out.println("操作失败,本系统内不存在此书");
}
}
这里也仅仅是一些简单的逻辑判断
注意:if( bookShelf.getBooks()[i].getIsBorrowed() ) { 这行代码
if 判断语句的括号内规定是布尔表达式,而我们 getIsBorrowed() 方法的返回值正是 true 或 false ,利用逻辑判断即可简化代码
public class Return implements Operate {
@Override
// 重写 Operate 接口中的 operate 方法
public void operate(BookShelf bookShelf) {
System.out.println("请输入您要归还的书名");
Scanner scanner = new Scanner(System.in);
String borrowedName = scanner.nextLine();
int size = bookShelf.getSize();
for (int i = 0; i < size; i++) {
if(bookShelf.getBooks()[i].getBookName().equals(borrowedName)) {
if(bookShelf.getBooks()[i].getIsBorrowed()) {
// if(bookShelf.getBooks()[i].getIsBorrowed() == true) {
bookShelf.getBooks()[i].setIsBorrowed(false);
System.out.println("归还成功\n");
return;
}else {
System.out.println("操作失败,该书尚未被借出\n");
return;
}
}
}
System.out.println("操作失败,本系统内不存在此书");
}
}
和上面 Borrow 类同理,只需理清楚逻辑即可轻松写出代码
到现在,所有的代价都已经解析过啦,下面附上源码
注意分清代码在=哪个包中的哪个类噢
// book 包
// Book类
public class Book {
private String bookName;
private String author;
private double price;
private boolean isBorrowed = false;
public Book(String bookName, String author, double price) {
this.bookName = bookName;
this.author = author;
this.price = price;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public boolean getIsBorrowed() {
return isBorrowed;
}
public void setIsBorrowed(boolean isBorrowed) {
this.isBorrowed = isBorrowed;
}
}
// book 包
// BookShelf类
public class BookShelf {
private Book[] books = new Book[10];
private int size;
public BookShelf() {
books[0] = new Book("瓦尔登湖", "张三", 39.9);
books[1] = new Book("百年孤独", "李四", 49.9);
books[2] = new Book("赎罪", "王五", 38.8);
this.size = 3;
}
public Book[] getBooks() {
return books;
}
public void setBooks(Book[] books) {
this.books = books;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public void printBookShelf(BookShelf bookShelf) {
int size = bookShelf.getSize();
for (int i = 0; i < size; i++) {
System.out.print(i + 1 + ": ");
System.out.println("书名: "+ bookShelf.getBooks()[i].getBookName() + " "
+ "作者: " + bookShelf.getBooks()[i].getAuthor() + " "
+ "价格:"+ bookShelf.getBooks()[i].getPrice() + "元 "
+ (bookShelf.getBooks()[i].getIsBorrowed()?" 已背借出":" 未被借出"));
}
}
}
// user 包
// USer 父类
public abstract class User {
protected String name;
protected Operate[] operates; //数组,存放不同的操作(对象)
public User(String name) {
this.name = name;
}
public abstract void menu();
// 重点!
public void doOperate(int operateOption, BookShelf bookShelf) {
this.operates[operateOption].operate(bookShelf);
}
}
// user 包
// Administrator 子类
public class Administrator extends User {
// 构造方法
public Administrator(String name) {
super(name);
this.operates = new Operate[]{
new Exit(),
new Show(),
new Add(),
new Delete(),
new Find()
};
}
public void menu() {
System.out.println("——————————————");
System.out.println("hello " + this.name );
System.out.println("1.显示图书信息" );
System.out.println("2.增加图书信息" );
System.out.println("3.删除图书信息" );
System.out.println("4.查询图书信息" );
System.out.println("0.退出系统" );
System.out.println("——————————————");
}
}
// user 包
// Customer 子类
public class Customer extends User{
// 构造方法
public Customer(String name) {
super(name);
this.operates = new Operate[]{
new Exit(),
new Find(),
new Borrow(),
new Return(),
};
}
public void menu() {
System.out.println("——————————————");
System.out.println("hello " + this.name);
System.out.println("1.查询图书信息");
System.out.println("2.借阅图书");
System.out.println("3.归还图书");
System.out.println("0.退出系统");
System.out.println("——————————————");
}
}
// operate 包
// Operate 接口
public interface Operate {
void operate(BookShelf bookShelf);
}
// operate 包
// Add 类
public class Add implements Operate {
@Override
public void operate(BookShelf bookShelf) {
System.out.println("请依次输入:书名、作者、价格");
Scanner scanner1 = new Scanner(System.in);
String newBookName = scanner1.nextLine();
Scanner scanner2 = new Scanner(System.in);
String newAuthor = scanner2.nextLine();
Scanner scanner3 = new Scanner(System.in);
double newPrice = scanner3.nextDouble();
int size = bookShelf.getSize();
bookShelf.getBooks()[size] = new Book(newBookName, newAuthor, newPrice);
System.out.println("增加成功\n");
bookShelf.setSize(++size);
}
}
// operate 包
// Delete 类
public class Delete implements Operate {
@Override
public void operate(BookShelf bookShelf) {
int size = bookShelf.getSize();
bookShelf.printBookShelf(bookShelf);
System.out.print("请输入您要删除第几本书:");
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();
for (int i = num - 1; i < size - 1; i++) {
bookShelf.getBooks()[i] = bookShelf.getBooks()[i + 1];
}
bookShelf.setSize(--size);
System.out.println("删除成功\n");
bookShelf.printBookShelf(bookShelf);
}
}
// operate 包
// Find 类
public class Find implements Operate {
@Override
public void operate(BookShelf bookShelf) {
System.out.println("请输入你要查询的书名");
Scanner scanner = new Scanner(System.in);
String targetName = scanner.nextLine();
int size = bookShelf.getSize();
for (int i = 0; i < size; i++) {
if(bookShelf.getBooks()[i].getBookName().equals(targetName)) {
System.out.println("该书籍信息如下:");
System.out.println("书名: "+ bookShelf.getBooks()[i].getBookName() + " "
+ "作者: " + bookShelf.getBooks()[i].getAuthor() + " "
+ "价格: "+ bookShelf.getBooks()[i].getPrice() + "元 "
+ "是否被借出: " + bookShelf.getBooks()[i].getIsBorrowed());
return;
}
}
System.out.println("未查询到此书\n");
}
}
// operate 包
// Exit 类
public class Exit implements Operate {
@Override
public void operate(BookShelf bookShelf) {
System.out.println("感谢使用本系统,再见!");
System.exit(0);
}
}
// operate 包
// Show 类
public class Show implements Operate {
@Override
public void operate(BookShelf bookShelf) {
System.out.println("图书信息如下:");
bookShelf.printBookShelf(bookShelf);
}
}
// operate 包
// Borrow 类
public class Borrow implements Operate {
@Override
public void operate(BookShelf bookShelf) {
System.out.println("请输入您要借阅的书名");
Scanner scanner = new Scanner(System.in);
String borrowName = scanner.nextLine();
int size = bookShelf.getSize();
for (int i = 0; i < size; i++) {
if (bookShelf.getBooks()[i].getBookName().equals(borrowName)) {
if(bookShelf.getBooks()[i].getIsBorrowed()) {
// if (bookShelf.getBooks()[i].getIsBorrowed() == false) {
System.out.println("抱歉,该书已被借出\n");
return;
}else {
bookShelf.getBooks()[i].setIsBorrowed(true);
System.out.println("借阅成功\n");
return;
}
}
}
System.out.println("操作失败,本系统内不存在此书");
}
}
// operate 包
// Return 类
public class Return implements Operate{
@Override
public void operate(BookShelf bookShelf) {
System.out.println("请输入您要归还的书名");
Scanner scanner = new Scanner(System.in);
String borrowedName = scanner.nextLine();
int size = bookShelf.getSize();
for (int i = 0; i < size; i++) {
if(bookShelf.getBooks()[i].getBookName().equals(borrowedName)) {
if(bookShelf.getBooks()[i].getIsBorrowed()) {
// if(bookShelf.getBooks()[i].getIsBorrowed() == true) {
bookShelf.getBooks()[i].setIsBorrowed(false);
System.out.println("归还成功\n");
return;
}else {
System.out.println("操作失败,该书尚未被借出\n");
return;
}
}
}
System.out.println("操作失败,本系统内不存在此书");
}
}
以上就是本篇的全部内容了,虽然以目前所学的知识,写的图书管理系统还仅仅是皮毛,但结合了此前所学知识,是一个不错的巩固方式
博主认为难点主要在于
1️⃣如何 new 对象,new 什么对象?
2️⃣如何利用多态的思想
3️⃣如何利用接口
4️⃣最难的是如何面向对象,把这些知识串联起来,完整的写出这份代码
如果本篇对你有帮助,请点赞收藏支持一下,小手一抖就是对作者莫大的鼓励啦
上山总比下山辛苦
下篇文章见